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:
@@ -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
|
||||
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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.
|
@@ -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
|
||||
|
6
main.mk
6
main.mk
@@ -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.
|
||||
|
56
manifest
56
manifest
@@ -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.
|
||||
|
@@ -1 +1 @@
|
||||
14a18f4e3a3f35e636262a253364ab1e8054ed38c0c7fd482633522cbcf5ffc4
|
||||
7d27451804e525190f8e67da75aaeb3bf2de677021f7566c6681398e60a88c72
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
22
src/select.c
22
src/select.c
@@ -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) */
|
||||
){
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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() */
|
||||
|
130
src/tclsqlite.c
130
src/tclsqlite.c
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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*);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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
20
test/dblwidth-a.sql
Normal 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;
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user