Compare commits

..

70 Commits

Author SHA1 Message Date
drh 825026251f ADd SQLITE_USE_ONLY_WIN32 to the Default configuration for testing on
Windows.  Take it off of Stdcall.

FossilOrigin-Name: 8ace3f15e4f7e8249bf4cf558ceecdf67792bb7801529ef86b4d36363bb8ff8c
2024-09-03 17:01:07 +00:00
drh fd486258a0 Enhance the "errors" command in testrunner.tcl so that it accepts the
"-s" or "--summary" argument to see a list of failed jobs, and so that
an additional argument is a GLOB pattern that restricts the output to
jobs whose names match that pattern.

FossilOrigin-Name: dcbebe30f594a99e23b5ccd8d199b92118204a3e52e75c78d98c394601252e81
2024-09-03 16:04:34 +00:00
drh 940cdc94f3 Fix ext/consio so that it works correctly with SQLITE_USE_ONLY_WIN32.
FossilOrigin-Name: efc6f3d7e92a25f440fb8d392daf325af5ca7dca104a5bb4bd59f7df93af53b0
2024-09-03 14:15:57 +00:00
drh 23a16c8387 In testrunner.tcl, compile the Windows Default configuration using
SQLITE_ENABLE_STMT_SCANSTATUS.

FossilOrigin-Name: 49e8b1635f29d9fd0dc2ef6e312fd4129f2283f68e9423d95ff9b55077688ad7
2024-09-03 14:00:36 +00:00
drh e6e49bfef2 Fix harmless compiler warnings in the percentile extension.
FossilOrigin-Name: c5557f281c6294b6db6682349d245feac7c6ce7f4f61356f486afdf186c566c4
2024-09-03 12:41:21 +00:00
drh 06638117bb In testrunner.tcl, allow setting njob to zero, which causes no new jobs
to be launched and for the process to shut down once all current jobs are
completed.

FossilOrigin-Name: 0ef65fd4ba17def4c13986365b3af300c4024725af4bc314845d1af8be568ab4
2024-09-03 10:53:32 +00:00
larrybr 22cd1eec5a Cause cfGets() (under SQLITE_USE_ONLY_WIN32) to better emulate fgets().
FossilOrigin-Name: 2d783524d1671d988ebb1b21c83de99c9f335963b6c20cf4df612f58c13da913
2024-09-03 02:09:13 +00:00
drh 7c6f2880aa Fix possible NULL pointer dereference following OOM in the new error reporting
logic of the percentile extension.

FossilOrigin-Name: 7891a266c4425722ae8b9231397ef9e42e2432be9e6b70632dfaf9ff15300d2c
2024-09-02 21:59:31 +00:00
dan 70989b6f59 Fix a technically undefined signed integer overflow in fts5.
FossilOrigin-Name: e6bec37ea1ca51e1d048941ce4c5211d8fc5c5e3556a1441f9c79b036843f9e3
2024-09-02 18:41:59 +00:00
drh ef7c692baf Make the percential extension easier to incorporate as a built-in on Windows
applications.

FossilOrigin-Name: 831e2be4117dc7f5113f66d3e484ca34e4405444ac7b0def12ee9a00608d40da
2024-09-02 17:27:10 +00:00
drh da52f11250 Remove some debug/test code from percentile. Make the extension easier to
statically link.

FossilOrigin-Name: 6e5f146e274b210749dd8923a2da56905eb098b5a66699ff9130e3e51b1ff662
2024-09-02 14:46:56 +00:00
drh 7a29505e57 Enhance the percentile extension to support percentile_cont() and
percentile_disc().  Add support for ordered-set aggregate notation in 
the parser when compiling with SQLITE_ENABLE_ORDERED_SET_AGGREGATES.  A
new function property SQLITE_SELFORDER1 must appear on any aggregate function
that wants to take advantage of the ordered-set aggregate notation.

FossilOrigin-Name: 557bd245ef24af15da1374762bbeb9b8b0241da06e604efdf00d567a9ed09216
2024-09-02 12:07:37 +00:00
drh d281889ac8 Improved error messages on percentile functions. More tests cases for
percentile and for ordered-set aggregates.

FossilOrigin-Name: e1bca168e70335fa2f9537632fd16e374c566a564fab4974c0b8f61cb63d08ce
2024-09-02 11:17:04 +00:00
drh a955ec806a Change the name of the enabling compile-time macro to
SQLITE_ENABLE_ORDERED_SET_AGGREGATES.

FossilOrigin-Name: 3b1cdddf8339cc339ec74cd8be2bfa42e62b500048a444eb9e5d9817bc4702ae
2024-09-02 09:40:37 +00:00
drh b5df31d15f More internal documentation improvements.
FossilOrigin-Name: 8b91b74931c36e1955ef933a07d8ec40c8b54c882efe7084d179168867c5244f
2024-09-01 23:56:14 +00:00
drh b9a6e42a55 Improved documentation of recent enhancements to the percentile extension.
FossilOrigin-Name: 51e7b4c9cf19a5986432a76c5fd30cef715c170a403d7b4304a8c5888c445a91
2024-09-01 23:47:20 +00:00
drh 1c30df3598 The WITHIN GROUP (ORDER BY ...) syntax is now a compile-time option:
SQLITE_ENABLE_ORDERED_SET_FUNCS.  There is no increment in the code size
if the option is omitted.

FossilOrigin-Name: c9367e2532d653738af27c4d92810eb648a9e12f72d7223017c87cb0dddc6804
2024-09-01 23:27:34 +00:00
drh ca447020ae Implement percentile_cont() and percentile_disc().
FossilOrigin-Name: b1a93f67d6b21df6fe3247c9333fead61dd425574f66ea3eb06b80c2b06f616a
2024-09-01 20:24:24 +00:00
drh 7aa01a0ffc No prepare-time penality for ordered-set aggregates for applications that
do not use them.

FossilOrigin-Name: e070c16d2183312e416ff6af770346041e4d3836c4db2c9ea6049f63fb0eaa07
2024-09-01 19:19:26 +00:00
drh 5d5d6194c9 Merge fixes from trunk into the ordere-set-agg branch.
FossilOrigin-Name: 7528ddcfdf155116353266e00e6408c526e29f04cb00ca2d9e84b105329b17c0
2024-09-01 18:57:52 +00:00
drh c97ad9b4e1 Improved sort function in the percentile extension.
FossilOrigin-Name: 9f84e8d59bcda642e732565e840f6a880a01b2fc65af2651248f6a8a6e1cb65a
2024-09-01 18:54:31 +00:00
drh 41155d8885 Fix to the quicksort algorithm in the percentile extension.
FossilOrigin-Name: 54313f74b24c46f1afa1ff082ef569fa46938527095be358015e7047e17702ac
2024-09-01 10:52:20 +00:00
drh df2d14b86e Add error checking: Do not allow functions other than those in the
percentile extension to use the ordered-set aggregate notation.

FossilOrigin-Name: 317d901429303340290334dbe7680a36339df0a50b586e3f71b6c5e5eba6d411
2024-08-31 22:22:24 +00:00
drh a239ece378 Demonstration of how ordered-set aggregates might be parsed and integrated
into the existing parse tree, should we decide to support them.

FossilOrigin-Name: ef9777890001ba0122d3add799795e118fd87243f42731ab84d4748b67605647
2024-08-31 20:09:37 +00:00
drh c1042cd133 Include percentile() and merge() in the fuzzcheck test utility.
FossilOrigin-Name: d1d0942a947803d45a1fd9068f3518cf412178b6b9bafcb82db44c52d5820c11
2024-08-31 19:24:17 +00:00
drh 65b1244781 Omit the percentile_cont() function added by [095c22e62248f8ef] (and not yet
released) since its usage conflicts with the PG percentile_cont() function.

FossilOrigin-Name: 3fe0a852978f3f1218e37a58f0d3b54016d4116a3301aa32efa7c4c12c767755
2024-08-31 18:35:10 +00:00
drh 49af3dfbf4 Allow percentile() and median() to act as window functions.
FossilOrigin-Name: 94cf96af8fee55449080655bddf81cbf5c078a02d7bb5dd7e4903b36f83a8c07
2024-08-31 18:08:31 +00:00
drh a5315a6ece Still more test cases.
FossilOrigin-Name: f09904608195dac38172b0dd4dcab3190f33c116d468beff27f913a7433b400e
2024-08-31 17:50:06 +00:00
drh f138110dfd Add more test cases.
FossilOrigin-Name: 0d0e5456793b4bef673ebc7fcc1c393a6d3c817363d948ddfe06d60eab56dc24
2024-08-31 17:27:55 +00:00
drh ad8ec9db63 Avoid unnecessary sort operations when running one of the percentile
aggregates as a window function.

FossilOrigin-Name: 5d311536211eb1e3c887ceb7e6516d3900e6eebbccc8c445dd43cdd556182728
2024-08-31 16:55:14 +00:00
drh 129767958a Test cases added.
FossilOrigin-Name: 25e68229843cc84978955817285550085d1306ba4ce3b0517dd00e5d05b9ae0a
2024-08-31 15:02:07 +00:00
drh 90fa4c7b2c Enhance the percentile() and median() extension functions so that they can be
window functions.

FossilOrigin-Name: 4d0e3df4b9c609755977b8a462126242d2be1310c0122a8d4ba76d98d32a7230
2024-08-31 14:31:17 +00:00
drh 3196c349d1 Do not fail the omittest if ICU libraries are not installed.
FossilOrigin-Name: ddc55efd2d59df3f20743b0533550436da945453c069025a3f871d28d40e13d4
2024-08-30 17:33:25 +00:00
drh 0337b9a628 New makefile target: "tidy". The "tidy" target removes all build products
be leaves behind test results.  The "clean" target has been enhanced to do a
better job.  The tool/omittest.tcl script is rewritten to work on the
configure-generated Makefile and to require no arguments.

FossilOrigin-Name: e48add02695a41b26a04e7942b5333e2bf4dc5598e363367aea3a4690982667d
2024-08-30 16:51:41 +00:00
drh 6cb12337b9 A couple of #defines so that the build work with SQLITE_OMIT_FLOATING_POINT.
FossilOrigin-Name: be768f80c703ac1645251ccbac83e07b3ea4cc231c8ea7e66374a4f78361f10b
2024-08-30 16:43:36 +00:00
drh c589d5ab06 Rework the tool/omittest.tcl script so that it works with the
configure-generated Makefile, and requires no arguments.
Update the configure-generated Makefile with a new "tidy" target which
is like "clean" except that is preserves test logs.  Use "make tidy" to
force everything to be recompiled from scratch without destroying logs.

FossilOrigin-Name: 99491df19d68df1f0515bd5ec9240ef3dd6e0fa38a6c837a38a16a873f8e2cbb
2024-08-30 16:24:49 +00:00
drh 28db1a68ba Improvements to "make clean" on unix.
FossilOrigin-Name: a1d775f07528192b09566ff1546b067ffbee0db5812e424e6b7f3cc33a67dc83
2024-08-30 12:10:28 +00:00
drh 11397ce104 In the testrunner.tcl status report, try to provide a rough estimate of
the time remaining.

FossilOrigin-Name: 90bc616d20e8c247691c45de2a28d41c1632b21152dc34253eefc179a90ab31f
2024-08-30 01:11:19 +00:00
drh 494ba30c9b Sync the autoconf/Makefile.msc with the main ./Makefile.msc
FossilOrigin-Name: 9de47c3611ca05e03a661807a06c6c5c0b5c6548ea7a8d73cb63832d2dff9d0e
2024-08-29 23:32:16 +00:00
drh 6a18c9e06a All makefiles are responsive to OPTIONS=... command-line arguments, and add
the RHS value of OPTIONS= to builds and to lemon and other build steps that
might respond to -D or -U options.

FossilOrigin-Name: 854b3776ee1fcaa5931e3a0ed104978ca350d218e553586d1c40c2420e1be498
2024-08-29 18:32:56 +00:00
dan ccd34894e1 Fix a case where the BTCF_AtLast flag was being left set incorrectly. This was causing obscure window function queries to fail.
FossilOrigin-Name: e042eb024738a83eed92cd2dfac3d2a50d2589715a3d81b1a494564dd7d8e7fa
2024-08-29 16:27:57 +00:00
drh c1547d1f7a Do not allow sqlite3_blob_open() to work on a any table that contains
generated columns, even columns of the table which are not generated themselves,
because such columns might be part of the expression of a STORED column.
This restriction could be relaxed some, but that would be a lot of code
for something that nobody ever uses.

FossilOrigin-Name: 6e84947123339f0ea2b7dabc6134a621eed09317f81647f15870ed50a0f7d1bc
2024-08-28 19:13:16 +00:00
dan 50ca8af6f2 Fix a dropped error code in fts5.
FossilOrigin-Name: df55502e4f412e5b1daccf82f11fa4eb932047d9972dcd16e36be00cf09f78e1
2024-08-28 15:54:46 +00:00
drh 8db3fc5488 Update the README.md file to recommend running "devtest" instead of "mdevtest".
FossilOrigin-Name: eb016f66ea2c7ebacf8c57495843db3414602d062e4a430f2cc603c88b10c3f9
2024-08-28 13:55:46 +00:00
drh ba5994b181 Maybe [7420b13238da4e6b] was not such a good idea. Restore "make test" so
that it works as before - running a single-threaded test over the source tree
with options specified by ./configure and similar.  Instead, change the
"make devtest" target so that runs the automated multi-threaded tests on 
a standard configuration.

FossilOrigin-Name: dc9fee980d4f4b5a569628702e52cef9e5d8e6c69c2b84546dce47e3e514775e
2024-08-28 13:51:51 +00:00
drh 3341f5ce85 Minor wording change on testrunner output.
FossilOrigin-Name: 115e68597957a9ee80de7f554ee3768c992051687c8f07eaf3a9fcaab7efd44e
2024-08-28 13:34:20 +00:00
drh d6b56d65a8 Update the "make test" target so that it is really just "mdevtest" with
"srctree-check" and "sourcetest".

FossilOrigin-Name: 7420b13238da4e6bfb1589eaf3cfd842fe3c4b0f3b6a3b49c24cd70589bf4809
2024-08-28 12:10:51 +00:00
drh 4f2f91bf08 Further improvements to the status display in order to maximum the amount of
information shown on the limited screen realestate available when running
via "watch" or in continuous monitoring mode.  All details are still shown
when doing a stand-alone "status".

FossilOrigin-Name: 557a2c65f5ae1d8cb1858c17da0fe64fbfba83d787cfb7f2f21582960a8b9eac
2024-08-28 11:03:58 +00:00
drh 242e064978 Only limit the number of failures reported by testrunner status if using
VT100 cursor movement.  For a straight-up "status" command, show everything.

FossilOrigin-Name: 791237e0f4b67f0197ae11e966554edeade0c443289d2ade00470d23bf5e8ec8
2024-08-28 10:36:18 +00:00
drh 4a90f81a6d In the testrunner status display, limit the number of reported failed jobs
to avoid overflowing the terminal when there are many failures.

FossilOrigin-Name: ffeaa4d5d73871cbdf1ef70b9845d921ebdb96e964d232661a5048cab7d744ed
2024-08-28 10:25:44 +00:00
drh a88d61824d Disable shell test cases that require virtual tables when testfixture is
built using SQLITE_OMIT_VIRTUALTABLE.

FossilOrigin-Name: 8c73d54fd1e250fcd7f30741cfbd169af9aaecc2096c0c8a9486abaa064d69af
2024-08-28 09:47:29 +00:00
drh af43eddc23 Reenable SQLITE_OMIT_VIRTUALTABLE on the Device-One alignment for testrunner.
FossilOrigin-Name: 8f2cb357634ec0b5aef14f3d967e76db236f8899f3201efc80c264f548cc1b0b
2024-08-28 09:31:17 +00:00
drh b5b4ca2a11 Changes to the way "release" tests were constructed in [d03d35eebaf82709]
were incorrect.  Fixed here.  Also enhance --explain to chose permutation
configurations and so that PATTERNS on the the command line can match
against permutation configurations.

FossilOrigin-Name: 1f962ffc9e956a9d6311ed9c02fea13c0fe056283ee2c650a2312a258808b3b3
2024-08-27 22:28:03 +00:00
drh c3c645ef46 Improvements to --status overwrite in testrunner.
FossilOrigin-Name: 26372762ab1451eb95d29367f5b2534bde616a37e5e757e72ba2cfe42571d180
2024-08-27 21:44:45 +00:00
dan f5a9b58c8b Avoid reading the structure record from within the fts5 xConnect method.
FossilOrigin-Name: 6a6ce343b249e269229867b2c2f107a49ac8a8f24ad66801718ef01159655319
2024-08-27 20:37:30 +00:00
drh ce018f5bb3 Further minor improvements and tweaks to the testrunner --status display.
FossilOrigin-Name: 7d1ccc6dfc9abe053baaf39f68e9fb14001f5032a52b85fe1e4b752e48317536
2024-08-27 19:49:51 +00:00
drh 1a7cfbebb0 Fix typo in the previous check-in. Ensure that --status header lines do not
overflow and wrap.

FossilOrigin-Name: 2eaea67495fd9961b7145d829789889bf1d8fa7a834d40d1be43e7c74c233bc2
2024-08-27 19:48:19 +00:00
drh db05c66a16 In testrunner, when doing the --status updates to the screen, be sure to
overwrite dead text at the end of each line with spaces.

FossilOrigin-Name: 7c195f132cb48ee44124eb4af3532937493429f7c45f6ac611f7a9b128799ad7
2024-08-27 19:43:21 +00:00
drh 71475478a1 Further improvement to the status display in testrunner.tcl. Show the
number of errors and the number of test cases on the status summary.

FossilOrigin-Name: dbc1ac8692feccde271eaca78f2833c8bb7bf620088c8f975692d6ae2c8ba53a
2024-08-27 19:28:21 +00:00
dan c8edf07ca7 Modify the implementation of "wrapper" tokenizers to make them more robust in the case where the database connection is closed before the tokenizers are deleted.
FossilOrigin-Name: 7c0001d6eb43f89144eb84d9e30f575a3feed401d685a0d1f260692e419b2df2
2024-08-27 19:27:40 +00:00
drh d9bc2bb638 Improvements to testrunner.tcl: Show elapse time in MM:SS or HH:MM:SS.
Keep track of the total number of tests and the total number of errors
and report those values on a summary line at the end.

FossilOrigin-Name: 40b232924c973f8d94605946fff75acbe120d90634a2eaf38bd31649e9f1390b
2024-08-27 19:17:29 +00:00
dan 3c39f1f5d6 Add test code to drop an fts5 table with corrupt records in its shadow tables.
FossilOrigin-Name: ca21c942c30a3dbff0e7d118e105b847d80b5388c74d19c2eeea71581f8f40b8
2024-08-27 18:25:04 +00:00
drh dac0d0b310 Updates to testrunner: (1) Omit all testing of User-Auth.
(2) Automatically add the "*" wildcard before and after all pattern
arguments.  (3) Build the sqlite3 CLI for release tests.

FossilOrigin-Name: d03d35eebaf82709414c87cfa6abc9d2baf8d7e64c2627bad0fd5bbda3e78d60
2024-08-27 17:38:26 +00:00
drh 4a972bc1b8 Merge the SQLITE_USE_ONLY_WIN32 flag for consio into trunk.
FossilOrigin-Name: e9b03b082dcf141695140a6c2c50bf0dc577c3d64ab76f81dd22f0084eca26d6
2024-08-27 14:35:54 +00:00
drh 8aa9135f2c Only avoid all C-runtime I/O if the SQLITE_USE_ONLY_WIN32 flag is defined.
FossilOrigin-Name: 164b1e1962aa1e16bdf52e9e86d4cf9c9e09220c0821932ac8e390e82074185f
2024-08-27 14:25:52 +00:00
drh fcd65efcf1 Merge all the latests trunk enhancements into the win-dupe-crt-fio branch.
FossilOrigin-Name: 2d52db98f47fbcda0622c034b21c2fb19bf4345b88c5c565ae9e6f7128642e43
2024-08-27 13:57:43 +00:00
dan c013fa50db Changes to documentation comments in fts5.h.
FossilOrigin-Name: 886545a8d0e9cbf4911ecf747da0ea8aad702d79cb065dad01a04aa4f51da12b
2024-08-26 19:08:54 +00:00
drh 1321ea5010 Randomize the name of the attached database used to do VACUUM.
FossilOrigin-Name: 0f4e65d73a2b95932f36768c0d9925a2d265d9b395b886d8e492d1d519b2093c
2024-08-26 17:35:32 +00:00
larrybr 3a39c44c21 Fix a few compiler gripes.
FossilOrigin-Name: 2e74a938f771a889dd8c49648b5a125ff748835ba1925388cc6b379a0abde9ac
2024-01-10 20:13:38 +00:00
larrybr 20728a599e For CLI shell and other utilities, optionally avoid C runtime file I/O on Windows in favor of WIN32 calls, while nominally preserving FILE* API interfaces. (a WIP, awaiting build and testing)
FossilOrigin-Name: 6be68be17927e72b1f1c4b93e781b7e9235876b3ad9512fe168e5b9d0b7b763a
2024-01-10 05:52:02 +00:00
43 changed files with 1933 additions and 1000 deletions
+54 -43
View File
@@ -83,9 +83,13 @@ TEMP_STORE = -DSQLITE_TEMP_STORE=@TEMP_STORE@
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
# The same set of OMIT and ENABLE flags should be passed to the
# LEMON parser generator and the mkkeywordhash tool as well.
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
#
# Add OPTIONS=... on the command line to append additional options
# to the OPT_FEATURE_FLAGS.
#
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@ $(OPTIONS)
TCC += $(OPT_FEATURE_FLAGS)
TCC += $(OPT_FEATURE_FLAGS)
# Add in any optional parameters specified on the make commane line
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
@@ -646,6 +650,7 @@ FUZZCHECK_SRC += $(TOP)/test/fuzzinvariants.c
FUZZCHECK_SRC += $(TOP)/ext/recover/dbdata.c
FUZZCHECK_SRC += $(TOP)/ext/recover/sqlite3recover.c
FUZZCHECK_SRC += $(TOP)/test/vt02.c
FUZZCHECK_SRC += $(TOP)/ext/misc/percentile.c
FUZZCHECK_SRC += $(TOP)/ext/misc/randomjson.c
DBFUZZ_OPT =
ST_OPT = -DSQLITE_OS_KV_OPTIONAL
@@ -1178,6 +1183,7 @@ SHELL_DEP = \
$(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/memtrace.c \
$(TOP)/ext/misc/pcachetrace.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/shathree.c \
@@ -1363,9 +1369,14 @@ tcltest: ./testfixture$(TEXE)
testrunner: testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl
# Runs both fuzztest and testrunner, consecutively.
# This is the testing target preferred by the core SQLite developers.
# It runs tests under a standard configuration, regardless of how
# ./configure was run. The devs run "make devtest" prior to each
# check-in, at a minimum. Probably other tests too, but at least this
# one.
#
devtest: srctree-check testfixture$(TEXE) fuzztest testrunner
devtest: srctree-check sourcetest
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS)
mdevtest: srctree-check has_tclsh85
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS)
@@ -1381,16 +1392,19 @@ srctree-check: $(TOP)/tool/srctree-check.tcl
# Testing for a release
#
releasetest: srctree-check testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
releasetest: srctree-check has_tclsh85 verify-source
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
# Minimal testing that runs in less than 3 minutes
#
quicktest: ./testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
# Try to run tests on whatever options are specified by the
# ./configure. The developers seldom use this target. Instead
# they use "make devtest" which runs tests on a standard set of
# options regardless of how SQLite is configured. This "test"
# target is provided for legacy only.
#
test: srctree-check fuzztest sourcetest $(TESTPROGS) tcltest
@@ -1407,8 +1421,8 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
shelltest: $(TESTPROGS)
./testfixture$(TEXT) $(TOP)/test/permutations.test shell
shelltest:
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release shell
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in has_tclsh85
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
@@ -1594,43 +1608,40 @@ tclextension-uninstall:
tclextension-list:
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info
clean:
rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la
rm -f sqlite3.h opcodes.*
rm -rf .libs .deps
rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz
rm -f mkkeywordhash$(BEXE) keywordhash.h
rm -f mksourceid$(BEXE)
rm -f *.da *.bb *.bbg gmon.out
rm -rf tsrc .target_source
rm -f tclsqlite3$(TEXE)
rm -f testfixture$(TEXE) test.db
# Remove build products sufficient so that subsequent makes will recompile
# everything from scratch. Do not remove:
#
# * test results and test logs
# * output from ./configure
#
tidy:
rm -f *.lo *.la *.o *.c *.da *.bb *.bbg gmon.* *.rws sqlite3$(TEXE)
rm -f fts5.h keywordhash.h opcodes.h sqlite3.h sqlite3ext.h sqlite3session.h
rm -rf .libs .deps tsrc .target_source
rm -f lemon$(BEXE) sqlite*.tar.gz
rm -f mkkeywordhash$(BEXE) mksourceid$(BEXE)
rm -f parse.* fts5parse.*
rm -f tclsqlite3$(TEXE) $(TESTPROGS)
rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
rm -f wordcount$(TEXE) changeset$(TEXE)
rm -f version-info$(TEXT)
rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
rm -f sqlite3.c
rm -f sqlite3rc.h
rm -f shell.c sqlite3ext.h
rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe
rm -f rbu rbu.exe
rm -f srcck1 srcck1.exe
rm -f fuzzershell fuzzershell.exe
rm -f fuzzcheck fuzzcheck.exe
rm -f sqldiff sqldiff.exe
rm -f dbhash dbhash.exe
rm -f fts5.* fts5parse.*
rm -f threadtest5
rm -f src-verify
rm -f custom.rws
rm -f has_tclsh84 has_tclsh85
rm -f wordcount$(TEXE) changeset$(TEXE) version-info$(TEXE)
rm -f *.dll *.lib *.exp *.def *.pc *.vsix
rm -f sqlite3_analyzer$(TEXE)
rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
rm -f threadtest5$(TEXE)
rm -f src-verify has_tclsh*
# Removes build products and test logs. Retains ./configure outputs.
#
clean: tidy
rm -rf omittest* testrunner* testdir*
# Clean up everything. No exceptions.
#
distclean: clean
rm -f sqlite_cfg.h config.log config.status libtool Makefile sqlite3.pc \
$(TESTPROGS)
rm -f sqlite_cfg.h config.log config.status Makefile $(LIBTOOL)
#
# Windows section
+32 -5
View File
@@ -379,6 +379,7 @@ SQLITE_TCL_DEP =
# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
OPT_FEATURE_FLAGS = $(OPT_XTRA)
!IF $(MINIMAL_AMALGAMATION)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=1
@@ -392,6 +393,14 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
# Additional feature-options above and beyond what are normally used can be
# be added using OPTIONS=.... on the command-line. These values are
# appended to the OPT_FEATURE_FLAGS variable.
#
!IFDEF OPTIONS
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) $(OPTIONS)
!ENDIF
# Should the session extension be enabled? If so, add compilation options
# to enable it.
#
@@ -1758,6 +1767,7 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\percentile.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
@@ -2304,6 +2314,7 @@ SHELL_DEP = \
$(TOP)\ext\misc\ieee754.c \
$(TOP)\ext\misc\memtrace.c \
$(TOP)\ext\misc\pcachetrace.c \
$(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\regexp.c \
$(TOP)\ext\misc\series.c \
$(TOP)\ext\misc\shathree.c \
@@ -2535,6 +2546,13 @@ queryplantest: testfixture.exe shell
fuzztest: fuzzcheck.exe
.\fuzzcheck.exe $(FUZZDATA)
# Legacy testing target for third-party integrators. The SQLite
# developers seldom use this target themselves. Instead
# they use "nmake /f Makefile.msc devtest" which runs tests on
# a standard set of options
#
test: $(TESTPROGS) sourcetest fuzztest tcltest
# Minimal testing that runs in less than 3 minutes (on a fast machine)
#
quicktest: testfixture.exe sourcetest
@@ -2544,7 +2562,6 @@ quicktest: testfixture.exe sourcetest
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test: $(TESTPROGS) sourcetest fuzztest tcltest
# The veryquick.test TCL tests.
#
@@ -2558,17 +2575,27 @@ tcltest: testfixture.exe
testrunner: testfixture.exe
.\testfixture.exe $(TOP)\test\testrunner.tcl
# Runs both fuzztest and testrunner, consecutively.
# This is the testing target preferred by the core SQLite developers.
# It runs tests under a standard configuration. The devs run
# "nmake /f Makefile.msc devtest" prior to each check-in, at a minimum.
# Probably other tests too, but at least this one.
#
devtest: testfixture.exe fuzztest testrunner
devtest: srctree-check sourcetest
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest
mdevtest:
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest
# Validate that various generated files in the source tree
# are up-to-date.
#
srctree-check: $(TOP)\tool\srctree-check.tcl
$(TCLSH_CMD) $(TOP)\tool\srctree-check.tcl
# Testing for a release
#
releasetest: testfixture.exe
testfixture.exe $(TOP)\test\testrunner.tcl release
releasetest:
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release
smoketest: $(TESTPROGS)
+14 -2
View File
@@ -109,7 +109,7 @@ For example:
../sqlite/configure ;# Run the configure script
make sqlite3 ;# Builds the "sqlite3" command-line tool
make sqlite3.c ;# Build the "amalgamation" source file
make mdevtest ;# Run development tests (requires tcl-dev)
make devtest ;# Run development tests (requires tcl-dev)
make releasetest ;# Run full release tests (requires tcl-dev)
make sqldiff ;# Builds the "sqldiff" command-line tool
make sqlite3_analyzer ;# Builds the "sqlite3_analyzer" tool (requires tcl-dev)
@@ -128,6 +128,13 @@ Almost all makefile targets require a "tclsh" TCL interpreter
version 8.6 or later. The targets marked with "(requires tcl-dev)" also require
the TCL development libraries.
On "make" command-lines, one can add "OPTIONS=..." to specify additional
compile-time options over and above those set by ./configure. For example,
to compile with the SQLITE_OMIT_DEPRECATED compile-time option, one could say:
./configure --enable-all
make OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3
The configure script uses autoconf 2.61 and libtool. If the configure
script does not work out for you, there is a generic makefile named
"Makefile.linux-gcc" in the top directory of the source tree that you
@@ -156,13 +163,18 @@ Build using Makefile.msc. Example:
nmake /f Makefile.msc sqlite3.exe
nmake /f Makefile.msc sqlite3.c
nmake /f Makefile.msc mdevtest
nmake /f Makefile.msc devtest
nmake /f Makefile.msc releasetest
nmake /f Makefile.msc tclextension-install
There are many other makefile targets. See comments in Makefile.msc for
details.
As with the unix Makefile, the OPTIONS=... argument can be passed on the nmake
command-line to enable new compile-time options. For example:
nmake /f Makefile.msc OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3.exe
## Source Tree Map
* **src/** - This directory contains the primary source code for the
+9
View File
@@ -301,6 +301,7 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
OPT_FEATURE_FLAGS = $(OPT_XTRA)
!IF $(MINIMAL_AMALGAMATION)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=1
@@ -314,6 +315,14 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
# Additional feature-options above and beyond what are normally used can be
# be added using OPTIONS=.... on the command-line. These values are
# appended to the OPT_FEATURE_FLAGS variable.
#
!IFDEF OPTIONS
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) $(OPTIONS)
!ENDIF
# Should the session extension be enabled? If so, add compilation options
# to enable it.
#
+89 -2
View File
@@ -595,6 +595,93 @@ oPutbUtf8(const char *cBuf, int nAccept){
# endif
}
/*
** Flush the given output stream. Return non-zero for success, else 0.
*/
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
SQLITE_INTERNAL_LINKAGE int
fFlushBuffer(FILE *pfOut){
# if CIO_WIN_WC_XLATE && !defined(SHELL_OMIT_FIO_DUPE)
return FlushFileBuffers(handleOfFile(pfOut))? 1 : 0;
# else
return fflush(pfOut);
# endif
}
#endif
#if CIO_WIN_WC_XLATE \
&& !defined(SHELL_OMIT_FIO_DUPE) \
&& defined(SQLITE_USE_ONLY_WIN32)
static struct FileAltIds {
int fd;
HANDLE fh;
} altIdsOfFile(FILE *pf){
struct FileAltIds rv = { _fileno(pf) };
union { intptr_t osfh; HANDLE fh; } fid = {
(rv.fd>=0)? _get_osfhandle(rv.fd) : (intptr_t)INVALID_HANDLE_VALUE
};
rv.fh = fid.fh;
return rv;
}
SQLITE_INTERNAL_LINKAGE size_t
cfWrite(const void *buf, size_t osz, size_t ocnt, FILE *pf){
size_t rv = 0;
struct FileAltIds fai = altIdsOfFile(pf);
int fmode = _setmode(fai.fd, _O_BINARY);
_setmode(fai.fd, fmode);
while( rv < ocnt ){
size_t nbo = osz;
while( nbo > 0 ){
DWORD dwno = (nbo>(1L<<24))? 1L<<24 : (DWORD)nbo;
BOOL wrc = TRUE;
BOOL genCR = (fmode & _O_TEXT)!=0;
if( genCR ){
const char *pnl = (const char*)memchr(buf, '\n', nbo);
if( pnl ) nbo = pnl - (const char*)buf;
else genCR = 0;
}
if( dwno>0 ) wrc = WriteFile(fai.fh, buf, dwno, 0,0);
if( genCR && wrc ){
wrc = WriteFile(fai.fh, "\r\n", 2, 0,0);
++dwno; /* Skip over the LF */
}
if( !wrc ) return rv;
buf = (const char*)buf + dwno;
nbo += dwno;
}
++rv;
}
return rv;
}
/* An fgets() equivalent, using Win32 file API for actual input.
** Input ends when given buffer is filled or a newline is read.
** If the FILE object is in text mode, swallows 0x0D. (ASCII CR)
*/
SQLITE_INTERNAL_LINKAGE char *
cfGets(char *cBuf, int n, FILE *pf){
int nci = 0;
struct FileAltIds fai = altIdsOfFile(pf);
int fmode = _setmode(fai.fd, _O_BINARY);
BOOL eatCR = (fmode & _O_TEXT)!=0;
_setmode(fai.fd, fmode);
while( nci < n-1 ){
DWORD nr;
if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break;
if( nr>0 && (!eatCR || cBuf[nci]!='\r') ){
nci += nr;
if( cBuf[nci-nr]=='\n' ) break;
}
}
if( nci < n ) cBuf[nci] = 0;
return (nci>0)? cBuf : 0;
}
# else
# define cfWrite(b,os,no,f) fwrite(b,os,no,f)
# define cfGets(b,n,f) fgets(b,n,f)
# endif
# ifdef CONSIO_EPUTB
SQLITE_INTERNAL_LINKAGE int
ePutbUtf8(const char *cBuf, int nAccept){
@@ -606,7 +693,7 @@ ePutbUtf8(const char *cBuf, int nAccept){
return conZstrEmit(ppst, cBuf, nAccept);
}else {
# endif
return (int)fwrite(cBuf, 1, nAccept, pfErr);
return (int)cfWrite(cBuf, 1, nAccept, pfErr);
# if CIO_WIN_WC_XLATE
}
# endif
@@ -672,7 +759,7 @@ SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
# endif
}else{
# endif
return fgets(cBuf, ncMax, pfIn);
return cfGets(cBuf, ncMax, pfIn);
# if CIO_WIN_WC_XLATE
}
# endif
+11 -4
View File
@@ -176,12 +176,19 @@ SQLITE_INTERNAL_LINKAGE int
ePutbUtf8(const char *cBuf, int nAccept);
#endif
/*
** Flush the given output stream. Return non-zero for success, else 0.
*/
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
SQLITE_INTERNAL_LINKAGE int
fFlushBuffer(FILE *pfOut);
#endif
/*
** Collect input like fgets(...) with special provisions for input
** from the console on platforms that require same. Defers to the
** C library fgets() when input is not from the console. Newline
** translation may be done as set by set{Binary,Text}Mode(). As a
** convenience, pfIn==NULL is treated as stdin.
** from the console on such platforms as require same. Newline
** translation may be done as set by set{Binary,Text}Mode().
** As a convenience, pfIn==NULL is treated as stdin.
*/
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn);
/* Like fGetsUtf8 except stream is always the designated input. */
+7 -6
View File
@@ -493,18 +493,19 @@ struct Fts5ExtensionApi {
**
** FTS5_TOKENIZER
**
** There is also an fts5_tokenizer object. This is an older version of
** fts5_tokenizer_v2. It is similar except that:
** There is also an fts5_tokenizer object. This is an older, deprecated,
** version of fts5_tokenizer_v2. It is similar except that:
**
** <ul>
** <li> There is no "iVersion" field, and
** <li> The xTokenize() method does not take a locale argument.
** </ul>
**
** fts5_tokenizer tokenizers should be registered with the xCreateTokenizer()
** function, instead of xCreateTokenizer_v2(). Tokenizers implementations
** registered using either API may be retrieved using both xFindTokenizer()
** and xFindTokenizer_v2().
** Legacy fts5_tokenizer tokenizers must be registered using the
** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
**
** Tokenizer implementations registered using either API may be retrieved
** using both xFindTokenizer() and xFindTokenizer_v2().
**
** SYNONYM SUPPORT
**
+1 -1
View File
@@ -2185,7 +2185,7 @@ static void fts5SegIterNext_None(
if( iOff<pIter->iEndofDoclist ){
/* Next entry is on the current page */
i64 iDelta;
u64 iDelta;
iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
pIter->iLeafOffset = iOff;
pIter->iRowid += iDelta;
+19 -17
View File
@@ -427,8 +427,7 @@ static int fts5InitVtab(
/* Load the initial configuration */
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
sqlite3Fts5IndexRollback(pTab->p.pIndex);
rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie-1);
}
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
@@ -2068,9 +2067,11 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
** Implementation of xBegin() method.
*/
static int fts5BeginMethod(sqlite3_vtab *pVtab){
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
fts5NewTransaction((Fts5FullTable*)pVtab);
return SQLITE_OK;
int rc = fts5NewTransaction((Fts5FullTable*)pVtab);
if( rc==SQLITE_OK ){
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
}
return rc;
}
/*
@@ -3267,7 +3268,9 @@ static int fts5NewTokenizerModule(
*/
typedef struct Fts5VtoVTokenizer Fts5VtoVTokenizer;
struct Fts5VtoVTokenizer {
Fts5TokenizerModule *pMod;
int bV2Native; /* True if v2 native tokenizer */
fts5_tokenizer x1; /* Tokenizer functions */
fts5_tokenizer_v2 x2; /* V2 tokenizer functions */
Fts5Tokenizer *pReal;
};
@@ -3287,7 +3290,9 @@ static int fts5VtoVCreate(
pNew = (Fts5VtoVTokenizer*)sqlite3Fts5MallocZero(&rc, sizeof(*pNew));
if( rc==SQLITE_OK ){
pNew->pMod = pMod;
pNew->x1 = pMod->x1;
pNew->x2 = pMod->x2;
pNew->bV2Native = pMod->bV2Native;
if( pMod->bV2Native ){
rc = pMod->x2.xCreate(pMod->pUserData, azArg, nArg, &pNew->pReal);
}else{
@@ -3309,11 +3314,10 @@ static int fts5VtoVCreate(
static void fts5VtoVDelete(Fts5Tokenizer *pTok){
Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
if( p ){
Fts5TokenizerModule *pMod = p->pMod;
if( pMod->bV2Native ){
pMod->x2.xDelete(p->pReal);
if( p->bV2Native ){
p->x2.xDelete(p->pReal);
}else{
pMod->x1.xDelete(p->pReal);
p->x1.xDelete(p->pReal);
}
sqlite3_free(p);
}
@@ -3331,9 +3335,8 @@ static int fts5V1toV2Tokenize(
int (*xToken)(void*, int, const char*, int, int, int)
){
Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
Fts5TokenizerModule *pMod = p->pMod;
assert( pMod->bV2Native );
return pMod->x2.xTokenize(p->pReal, pCtx, flags, pText, nText, 0, 0, xToken);
assert( p->bV2Native );
return p->x2.xTokenize(p->pReal, pCtx, flags, pText, nText, 0, 0, xToken);
}
/*
@@ -3348,10 +3351,9 @@ static int fts5V2toV1Tokenize(
int (*xToken)(void*, int, const char*, int, int, int)
){
Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
Fts5TokenizerModule *pMod = p->pMod;
assert( pMod->bV2Native==0 );
assert( p->bV2Native==0 );
UNUSED_PARAM2(pLocale,nLocale);
return pMod->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken);
return p->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken);
}
/*
+96 -15
View File
@@ -96,14 +96,14 @@ static int SQLITE_TCLAPI f5tDbAndApi(
rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
return TCL_ERROR;
}
sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
sqlite3_step(pStmt);
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
return TCL_ERROR;
}
@@ -392,7 +392,7 @@ static int SQLITE_TCLAPI xF5tApi(
CASE(12, "xSetAuxdata") {
F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc(sizeof(F5tAuxData));
if( pData==0 ){
Tcl_AppendResult(interp, "out of memory", 0);
Tcl_AppendResult(interp, "out of memory", (char*)0);
return TCL_ERROR;
}
pData->pObj = objv[2];
@@ -452,7 +452,7 @@ static int SQLITE_TCLAPI xF5tApi(
rc = p->pApi->xPhraseFirst(p->pFts, iPhrase, &iter, &iCol, &iOff);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0);
return TCL_ERROR;
}
for( ;iCol>=0; p->pApi->xPhraseNext(p->pFts, &iter, &iCol, &iOff) ){
@@ -683,7 +683,7 @@ static int SQLITE_TCLAPI f5tCreateFunction(
pApi, zName, (void*)pCtx, xF5tFunction, xF5tDestroy
);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
return TCL_ERROR;
}
@@ -750,7 +750,7 @@ static int SQLITE_TCLAPI f5tTokenize(
if( objc==5 ){
char *zOpt = Tcl_GetString(objv[1]);
if( strcmp("-subst", zOpt) ){
Tcl_AppendResult(interp, "unrecognized option: ", zOpt, 0);
Tcl_AppendResult(interp, "unrecognized option: ", zOpt, (char*)0);
return TCL_ERROR;
}
}
@@ -759,7 +759,7 @@ static int SQLITE_TCLAPI f5tTokenize(
return TCL_ERROR;
}
if( nArg==0 ){
Tcl_AppendResult(interp, "no such tokenizer: ", 0);
Tcl_AppendResult(interp, "no such tokenizer: ", (char*)0);
Tcl_Free((void*)azArg);
return TCL_ERROR;
}
@@ -767,13 +767,13 @@ static int SQLITE_TCLAPI f5tTokenize(
rc = pApi->xFindTokenizer(pApi, azArg[0], &pUserdata, &tokenizer);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], 0);
Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], (char*)0);
return TCL_ERROR;
}
rc = tokenizer.xCreate(pUserdata, &azArg[1], (int)(nArg-1), &pTok);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error in tokenizer.xCreate()", 0);
Tcl_AppendResult(interp, "error in tokenizer.xCreate()", (char*)0);
return TCL_ERROR;
}
@@ -787,7 +787,7 @@ static int SQLITE_TCLAPI f5tTokenize(
);
tokenizer.xDelete(pTok);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", 0);
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", (char*)0);
Tcl_DecrRefCount(pRet);
return TCL_ERROR;
}
@@ -1049,7 +1049,7 @@ static int SQLITE_TCLAPI f5tTokenizerLocale(
if( p->xToken==0 ){
Tcl_AppendResult(interp,
"sqlite3_fts5_locale may only be used by tokenizer callback", 0
"sqlite3_fts5_locale may only be used by tokenizer callback", (char*)0
);
return TCL_ERROR;
}
@@ -1098,7 +1098,7 @@ static int SQLITE_TCLAPI f5tTokenizerReturn(
if( p->xToken==0 ){
Tcl_AppendResult(interp,
"sqlite3_fts5_token may only be used by tokenizer callback", 0
"sqlite3_fts5_token may only be used by tokenizer callback", (char*)0
);
return TCL_ERROR;
}
@@ -1250,7 +1250,7 @@ static int SQLITE_TCLAPI f5tCreateTokenizer(
Tcl_AppendResult(interp, (
bV2 ? "error in fts5_api.xCreateTokenizer_v2()"
: "error in fts5_api.xCreateTokenizer()"
), 0);
), (char*)0);
return TCL_ERROR;
}
@@ -1540,12 +1540,92 @@ static int SQLITE_TCLAPI f5tRegisterOriginText(
Tcl_ResetResult(interp);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (void*)0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** This function is used to DROP an fts5 table. It works even if the data
** structures fts5 stores within the database are corrupt, which sometimes
** prevents a straight "DROP TABLE" command from succeeding.
**
** The first parameter is the database handle to use for the DROP TABLE
** operation. The second is the name of the database to drop the fts5 table
** from (i.e. "main", "temp" or the name of an attached database). The
** third parameter is the name of the fts5 table to drop.
**
** SQLITE_OK is returned if the table is successfully dropped. Or, if an
** error occurs, an SQLite error code.
*/
static int sqlite3_fts5_drop_corrupt_table(
sqlite3 *db, /* Database handle */
const char *zDb, /* Database name ("main", "temp" etc.) */
const char *zTab /* Name of fts5 table to drop */
){
int rc = SQLITE_OK;
int bDef = 0;
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, -1, &bDef);
if( rc==SQLITE_OK ){
char *zScript = sqlite3_mprintf(
"DELETE FROM %Q.'%q_data';"
"DELETE FROM %Q.'%q_config';"
"INSERT INTO %Q.'%q_data' VALUES(10, X'0000000000');"
"INSERT INTO %Q.'%q_config' VALUES('version', 4);"
"DROP TABLE %Q.'%q';",
zDb, zTab, zDb, zTab, zDb, zTab, zDb, zTab, zDb, zTab
);
if( zScript==0 ){
rc = SQLITE_NOMEM;
}else{
if( bDef ) sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
rc = sqlite3_exec(db, zScript, 0, 0, 0);
if( bDef ) sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, 0);
sqlite3_free(zScript);
}
}
return rc;
}
/*
** sqlite3_fts5_drop_corrupt_table DB DATABASE TABLE
**
** Description...
*/
static int SQLITE_TCLAPI f5tDropCorruptTable(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3 *db = 0;
const char *zDb = 0;
const char *zTab = 0;
int rc = SQLITE_OK;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB DATABASE TABLE");
return TCL_ERROR;
}
if( f5tDbPointer(interp, objv[1], &db) ){
return TCL_ERROR;
}
zDb = Tcl_GetString(objv[2]);
zTab = Tcl_GetString(objv[3]);
rc = sqlite3_fts5_drop_corrupt_table(db, zDb, zTab);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (void*)0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Entry point.
*/
@@ -1564,7 +1644,8 @@ int Fts5tcl_Init(Tcl_Interp *interp){
{ "sqlite3_fts5_token_hash", f5tTokenHash, 0 },
{ "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 },
{ "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 },
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 }
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 },
{ "sqlite3_fts5_drop_corrupt_table", f5tDropCorruptTable, 0 }
};
int i;
F5tTokenizerContext *pContext;
+7 -7
View File
@@ -680,11 +680,11 @@ do_test 12.0 {
do_catchsql_test 11.1 {
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
} {1 {vtable constructor failed: t1}}
} {1 {database disk image is malformed}}
do_catchsql_test 11.2 {
INSERT INTO t1(t1, rank) VALUES('merge', 500);
} {1 {vtable constructor failed: t1}}
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
#
@@ -1040,7 +1040,7 @@ do_test 16.0 {
do_catchsql_test 16.1 {
INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {vtable constructor failed: t1}}
} {1 {database disk image is malformed}}
#--------------------------------------------------------------------------
reset_db
@@ -1126,7 +1126,7 @@ do_test 17.0 {
do_catchsql_test 17.1 {
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
} {1 {vtable constructor failed: t1}}
} {1 {database disk image is malformed}}
#--------------------------------------------------------------------------
reset_db
@@ -1630,7 +1630,7 @@ do_test 20.0 {
do_catchsql_test 20.1 {
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
} {1 {vtable constructor failed: t1}}
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
@@ -2100,7 +2100,7 @@ do_test 22.0 {
do_catchsql_test 22.1 {
INSERT INTO t1(t1) VALUES('optimize');
} {1 {vtable constructor failed: t1}}
} {1 {database disk image is malformed}}
#--------------------------------------------------------------------------
reset_db
@@ -3700,7 +3700,7 @@ do_catchsql_test 32.1 {
highlight(t1, 2, '[', ']')
FROM t1('g + h')
WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank;
} {1 {vtable constructor failed: t1}}
} {1 {database disk image is malformed}}
do_catchsql_test 32.2 {
SELECT * FROM t3;
+94
View File
@@ -0,0 +1,94 @@
# 2024 Aug 28
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5corrupt8
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
}
do_execsql_test 1.1 {
UPDATE t1_data SET block='hello world' WHERE id=10
}
db close
sqlite3 db test.db
do_catchsql_test 1.2 {
SELECT * FROM t1
} {1 {database disk image is malformed}}
do_catchsql_test 1.3 {
DROP TABLE t1
} {0 {}}
do_execsql_test 1.4 {
SELECT * FROM sqlite_schema
}
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
}
do_execsql_test 2.1 {
UPDATE t1_config SET v=555 WHERE k='version'
}
db close
sqlite3 db test.db
do_catchsql_test 2.2 {
SELECT * FROM t1
} {1 {invalid fts5 file format (found 555, expected 4 or 5) - run 'rebuild'}}
do_catchsql_test 2.3 {
DROP TABLE t1
} {1 {invalid fts5 file format (found 555, expected 4 or 5) - run 'rebuild'}}
do_test 2.4 {
sqlite3_fts5_drop_corrupt_table db main t1
} {}
do_execsql_test 2.5 {
SELECT * FROM sqlite_schema
}
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
}
do_execsql_test 3.1 {
DELETE FROM t1_config;
}
db close
sqlite3 db test.db
do_catchsql_test 3.2 {
SELECT * FROM t1
} {1 {invalid fts5 file format (found 0, expected 4 or 5) - run 'rebuild'}}
do_catchsql_test 3.3 {
DROP TABLE t1
} {1 {invalid fts5 file format (found 0, expected 4 or 5) - run 'rebuild'}}
do_test 3.4 {
sqlite3_db_config db DEFENSIVE 1
} {1}
do_test 3.5 {
sqlite3_fts5_drop_corrupt_table db main t1
} {}
do_test 3.6 {
sqlite3_db_config db DEFENSIVE -1
} {1}
do_execsql_test 3.7 {
SELECT * FROM sqlite_schema
}
finish_test
+1 -1
View File
@@ -90,7 +90,7 @@ set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}]
do_faultsim_test 4 -faults oom-* -body {
db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'}
} -test {
faultsim_test_result {0 {0 {} 3}}
faultsim_test_result {0 {0 {} 2}}
}
#-------------------------------------------------------------------------
+21
View File
@@ -256,6 +256,27 @@ do_faultsim_test 10 -faults oom* -prep {
faultsim_test_result {0 hello}
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 11.0 {
CREATE VIRTUAL TABLE f1 USING fts5(content);
CREATE TABLE g1(id, content);
INSERT INTO g1 VALUES(30000, 'a b c');
INSERT INTO g1 VALUES(40000, 'd e f');
}
faultsim_save_and_close
do_faultsim_test 11 -faults oom* -prep {
faultsim_restore_and_reopen
} -body {
execsql {
INSERT INTO f1(rowid, content) SELECT id, content FROM g1;
}
} -test {
faultsim_test_result {0 {}}
}
finish_test
+56
View File
@@ -0,0 +1,56 @@
# 2024 September 3
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests focused on the integrity-check procedure.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5integrity2
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t2 USING fts5(a, detail='none');
BEGIN;
INSERT INTO t2(rowid, a) VALUES(-1, 'hello world');
INSERT INTO t2(rowid, a) VALUES(9223372036854775807, 'hello world');
COMMIT;
}
do_execsql_test 2.1 {
SELECT rowid FROM t2('hello AND world');
} {-1 9223372036854775807}
#-------------------------------------------------------------------------
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, detail='none');
CREATE TABLE r1(r);
WITH c(x) AS (VALUES(1) UNION SELECT x<<1 FROM c)
INSERT INTO r1(r) SELECT -1-x FROM c;
INSERT INTO t1(rowid, a) SELECT r, 'abc' FROM r1;
}
do_execsql_test 2.1 {
PRAGMA integrity_check;
} {ok}
do_execsql_test 2.2 {
SELECT rowid FROM t1('abc') ORDER BY +rowid;
} [db eval {SELECT r FROM r1 ORDER BY r}]
finish_test
+4 -4
View File
@@ -44,12 +44,12 @@ do_catchsql_test 1.2.2 {
do_catchsql_test 1.3.1 {
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads');
} {1 {no such cursor: 1}}
} {1 {no such cursor: 0}}
do_catchsql_test 1.3.2 {
SELECT a FROM t1
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
} {1 {no such cursor: 1}}
} {1 {no such cursor: 0}}
db close
sqlite3 db test.db
@@ -57,12 +57,12 @@ sqlite3 db test.db
do_catchsql_test 1.3.3 {
SELECT a FROM t1
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
} {1 {no such cursor: 1}}
} {1 {no such cursor: 0}}
fts5_aux_test_functions db
do_catchsql_test 1.3.4 {
SELECT fts5_columntext(t1) FROM t1('*reads');
} {1 {no such cursor: 1}}
} {1 {no such cursor: 0}}
#-------------------------------------------------------------------------
reset_db
+1 -1
View File
@@ -350,7 +350,7 @@ do_execsql_test 14.3 {
do_execsql_test 14.4 {
SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'
} {0 {} 3}
} {0 {} 2}
#-------------------------------------------------------------------------
reset_db
+303 -89
View File
@@ -11,7 +11,7 @@
******************************************************************************
**
** This file contains code to implement the percentile(Y,P) SQL function
** as described below:
** and similar as described below:
**
** (1) The percentile(Y,P) function is an aggregate function taking
** exactly two arguments.
@@ -60,31 +60,105 @@
**
** (13) A separate median(Y) function is the equivalent percentile(Y,50).
**
** (14) A separate percentile_cond(Y,X) function is the equivalent of
** percentile(Y,X*100.0).
** (14) A separate percentile_cont(Y,P) function is equivalent to
** percentile(Y,P/100.0). In other words, the fraction value in
** the second argument is in the range of 0 to 1 instead of 0 to 100.
**
** (15) A separate percentile_disc(Y,P) function is like
** percentile_cont(Y,P) except that instead of returning the weighted
** average of the nearest two input values, it returns the next lower
** value. So the percentile_disc(Y,P) will always return a value
** that was one of the inputs.
**
** (16) All of median(), percentile(Y,P), percentile_cont(Y,P) and
** percentile_disc(Y,P) can be used as window functions.
**
** Differences from standard SQL:
**
** * The percentile_cont(X,P) function is equivalent to the following in
** standard SQL:
**
** (percentile_cont(P) WITHIN GROUP (ORDER BY X))
**
** The SQLite syntax is much more compact. The standard SQL syntax
** is also supported if SQLite is compiled with the
** -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES option.
**
** * No median(X) function exists in the SQL standard. App developers
** are expected to write "percentile_cont(0.5)WITHIN GROUP(ORDER BY X)".
**
** * No percentile(Y,P) function exists in the SQL standard. Instead of
** percential(Y,P), developers must write this:
** "percentile_cont(P/100.0) WITHIN GROUP (ORDER BY Y)". Note that
** the fraction parameter to percentile() goes from 0 to 100 whereas
** the fraction parameter in SQL standard percentile_cont() goes from
** 0 to 1.
**
** Implementation notes as of 2024-08-31:
**
** * The regular aggregate-function versions of these routines work
** by accumulating all values in an array of doubles, then sorting
** that array using quicksort before computing the answer. Thus
** the runtime is O(NlogN) where N is the number of rows of input.
**
** * For the window-function versions of these routines, the array of
** inputs is sorted as soon as the first value is computed. Thereafter,
** the array is kept in sorted order using an insert-sort. This
** results in O(N*K) performance where K is the size of the window.
** One can imagine alternative implementations that give O(N*logN*logK)
** performance, but they require more complex logic and data structures.
** The developers have elected to keep the asymptotically slower
** algorithm for now, for simplicity, under the theory that window
** functions are seldom used and when they are, the window size K is
** often small. The developers might revisit that decision later,
** should the need arise.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#if defined(SQLITE3_H)
/* no-op */
#elif defined(SQLITE_STATIC_PERCENTILE)
# include "sqlite3.h"
#else
# include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#endif
#include <assert.h>
#include <string.h>
#include <stdlib.h>
/* The following object is the session context for a single percentile()
** function. We have to remember all input Y values until the very end.
/* The following object is the group context for a single percentile()
** aggregate. Remember all input Y values until the very end.
** Those values are accumulated in the Percentile.a[] array.
*/
typedef struct Percentile Percentile;
struct Percentile {
unsigned nAlloc; /* Number of slots allocated for a[] */
unsigned nUsed; /* Number of slots actually used in a[] */
double rPct; /* 1.0 more than the value for P */
char bSorted; /* True if a[] is already in sorted order */
char bKeepSorted; /* True if advantageous to keep a[] sorted */
char bPctValid; /* True if rPct is valid */
double rPct; /* Fraction. 0.0 to 1.0 */
double *a; /* Array of Y values */
};
/* Details of each function in the percentile family */
typedef struct PercentileFunc PercentileFunc;
struct PercentileFunc {
const char *zName; /* Function name */
char nArg; /* Number of arguments */
char mxFrac; /* Maximum value of the "fraction" input */
char bDiscrete; /* True for percentile_disc() */
};
static const PercentileFunc aPercentFunc[] = {
{ "median", 1, 1, 0 },
{ "percentile", 2, 100, 0 },
{ "percentile_cont", 2, 1, 0 },
{ "percentile_disc", 2, 1, 1 },
};
/*
** Return TRUE if the input floating-point number is an infinity.
*/
static int isInfinity(double r){
static int percentIsInfinity(double r){
sqlite3_uint64 u;
assert( sizeof(u)==sizeof(r) );
memcpy(&u, &r, sizeof(u));
@@ -92,13 +166,64 @@ static int isInfinity(double r){
}
/*
** Return TRUE if two doubles differ by 0.001 or less
** Return TRUE if two doubles differ by 0.001 or less.
*/
static int sameValue(double a, double b){
static int percentSameValue(double a, double b){
a -= b;
return a>=-0.001 && a<=0.001;
}
/*
** Search p (which must have p->bSorted) looking for an entry with
** value y. Return the index of that entry.
**
** If bExact is true, return -1 if the entry is not found.
**
** If bExact is false, return the index at which a new entry with
** value y should be insert in order to keep the values in sorted
** order. The smallest return value in this case will be 0, and
** the largest return value will be p->nUsed.
*/
static int percentBinarySearch(Percentile *p, double y, int bExact){
int iFirst = 0; /* First element of search range */
int iLast = p->nUsed - 1; /* Last element of search range */
while( iLast>=iFirst ){
int iMid = (iFirst+iLast)/2;
double x = p->a[iMid];
if( x<y ){
iFirst = iMid + 1;
}else if( x>y ){
iLast = iMid - 1;
}else{
return iMid;
}
}
if( bExact ) return -1;
return iFirst;
}
/*
** Generate an error for a percentile function.
**
** The error format string must have exactly one occurrance of "%%s()"
** (with two '%' characters). That substring will be replaced by the name
** of the function.
*/
static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
char *zMsg1;
char *zMsg2;
va_list ap;
va_start(ap, zFormat);
zMsg1 = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, pFunc->zName) : 0;
sqlite3_result_error(pCtx, zMsg2, -1);
sqlite3_free(zMsg1);
sqlite3_free(zMsg2);
}
/*
** The "step" function for percentile(Y,P) is called once for each
** input row.
@@ -112,28 +237,20 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
if( argc==1 ){
/* Requirement 13: median(Y) is the same as percentile(Y,50). */
rPct = 50.0;
}else if( sqlite3_user_data(pCtx)==0 ){
/* Requirement 3: P must be a number between 0 and 100 */
eType = sqlite3_value_numeric_type(argv[1]);
rPct = sqlite3_value_double(argv[1]);
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
|| rPct<0.0 || rPct>100.0 ){
sqlite3_result_error(pCtx, "2nd argument to percentile() is not "
"a number between 0.0 and 100.0", -1);
return;
}
rPct = 0.5;
}else{
/* Requirement 3: P must be a number between 0 and 1 */
/* Requirement 3: P must be a number between 0 and 100 */
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
eType = sqlite3_value_numeric_type(argv[1]);
rPct = sqlite3_value_double(argv[1]);
rPct = sqlite3_value_double(argv[1])/(double)pFunc->mxFrac;
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
|| rPct<0.0 || rPct>1.0 ){
sqlite3_result_error(pCtx, "2nd argument to percentile_cont() is not "
"a number between 0.0 and 1.0", -1);
|| rPct<0.0 || rPct>1.0
){
percentError(pCtx, "the fraction argument to %%s()"
" is not between 0.0 and %.1f",
(double)pFunc->mxFrac);
return;
}
rPct *= 100.0;
}
/* Allocate the session context. */
@@ -142,11 +259,12 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
/* Remember the P value. Throw an error if the P value is different
** from any prior row, per Requirement (2). */
if( p->rPct==0.0 ){
p->rPct = rPct+1.0;
}else if( !sameValue(p->rPct,rPct+1.0) ){
sqlite3_result_error(pCtx, "2nd argument to percentile() is not the "
"same for all input rows", -1);
if( !p->bPctValid ){
p->rPct = rPct;
p->bPctValid = 1;
}else if( !percentSameValue(p->rPct,rPct) ){
percentError(pCtx, "the fraction argument to %%s()"
" is not the same for all input rows");
return;
}
@@ -157,15 +275,14 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
/* If not NULL, then Y must be numeric. Otherwise throw an error.
** Requirement 4 */
if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
sqlite3_result_error(pCtx, "1st argument to percentile() is not "
"numeric", -1);
percentError(pCtx, "input to %%s() is not numeric");
return;
}
/* Throw an error if the Y value is infinity or NaN */
y = sqlite3_value_double(argv[0]);
if( isInfinity(y) ){
sqlite3_result_error(pCtx, "Inf input to percentile()", -1);
if( percentIsInfinity(y) ){
percentError(pCtx, "Inf input to %%s()");
return;
}
@@ -182,50 +299,80 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
p->nAlloc = n;
p->a = a;
}
p->a[p->nUsed++] = y;
if( p->nUsed==0 ){
p->a[p->nUsed++] = y;
p->bSorted = 1;
}else if( !p->bSorted || y>=p->a[p->nUsed-1] ){
p->a[p->nUsed++] = y;
}else if( p->bKeepSorted ){
int i;
i = percentBinarySearch(p, y, 0);
if( i<(int)p->nUsed ){
memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0]));
}
p->a[i] = y;
p->nUsed++;
}else{
p->a[p->nUsed++] = y;
p->bSorted = 0;
}
}
/*
** Sort an array of doubles.
** Interchange two doubles.
*/
static void sortDoubles(double *a, int n){
int iLt; /* Entries with index less than iLt are less than rPivot */
int iGt; /* Entries with index iGt or more are greater than rPivot */
#define SWAP_DOUBLE(X,Y) {double ttt=(X);(X)=(Y);(Y)=ttt;}
/*
** Sort an array of doubles.
**
** Algorithm: quicksort
**
** This is implemented separately rather than using the qsort() routine
** from the standard library because:
**
** (1) To avoid a dependency on qsort()
** (2) To avoid the function call to the comparison routine for each
** comparison.
*/
static void percentSort(double *a, unsigned int n){
int iLt; /* Entries before a[iLt] are less than rPivot */
int iGt; /* Entries at or after a[iGt] are greater than rPivot */
int i; /* Loop counter */
double rPivot; /* The pivot value */
double rTmp; /* Temporary used to swap two values */
if( n<2 ) return;
if( n>5 ){
rPivot = (a[0] + a[n/2] + a[n-1])/3.0;
}else{
rPivot = a[n/2];
assert( n>=2 );
if( a[0]>a[n-1] ){
SWAP_DOUBLE(a[0],a[n-1])
}
iLt = i = 0;
iGt = n;
while( i<iGt ){
if( n==2 ) return;
iGt = n-1;
i = n/2;
if( a[0]>a[i] ){
SWAP_DOUBLE(a[0],a[i])
}else if( a[i]>a[iGt] ){
SWAP_DOUBLE(a[i],a[iGt])
}
if( n==3 ) return;
rPivot = a[i];
iLt = i = 1;
do{
if( a[i]<rPivot ){
if( i>iLt ){
rTmp = a[i];
a[i] = a[iLt];
a[iLt] = rTmp;
}
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
iLt++;
i++;
}else if( a[i]>rPivot ){
do{
iGt--;
}while( iGt>i && a[iGt]>rPivot );
rTmp = a[i];
a[i] = a[iGt];
a[iGt] = rTmp;
SWAP_DOUBLE(a[i],a[iGt])
}else{
i++;
}
}
if( iLt>=2 ) sortDoubles(a, iLt);
if( n-iGt>=2 ) sortDoubles(a+iGt, n-iGt);
}while( i<iGt );
if( iLt>=2 ) percentSort(a, iLt);
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
/* Uncomment for testing */
#if 0
for(i=0; i<n-1; i++){
@@ -234,12 +381,61 @@ static void sortDoubles(double *a, int n){
#endif
}
/*
** Called to compute the final output of percentile() and to clean
** up all allocated memory.
** The "inverse" function for percentile(Y,P) is called to remove a
** row that was previously inserted by "step".
*/
static void percentFinal(sqlite3_context *pCtx){
static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
Percentile *p;
int eType;
double y;
int i;
assert( argc==2 || argc==1 );
/* Allocate the session context. */
p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
assert( p!=0 );
/* Ignore rows for which Y is NULL */
eType = sqlite3_value_type(argv[0]);
if( eType==SQLITE_NULL ) return;
/* If not NULL, then Y must be numeric. Otherwise throw an error.
** Requirement 4 */
if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
return;
}
/* Ignore the Y value if it is infinity or NaN */
y = sqlite3_value_double(argv[0]);
if( percentIsInfinity(y) ){
return;
}
if( p->bSorted==0 ){
assert( p->nUsed>1 );
percentSort(p->a, p->nUsed);
p->bSorted = 1;
}
p->bKeepSorted = 1;
/* Find and remove the row */
i = percentBinarySearch(p, y, 1);
if( i>=0 ){
p->nUsed--;
if( i<(int)p->nUsed ){
memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0]));
}
}
}
/*
** Compute the final output of percentile(). Clean up all allocated
** memory if and only if bIsFinal is true.
*/
static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
Percentile *p;
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
unsigned i1, i2;
double v1, v2;
double ix, vx;
@@ -247,21 +443,38 @@ static void percentFinal(sqlite3_context *pCtx){
if( p==0 ) return;
if( p->a==0 ) return;
if( p->nUsed ){
sortDoubles(p->a, p->nUsed);
ix = (p->rPct-1.0)*(p->nUsed-1)*0.01;
if( p->bSorted==0 ){
assert( p->nUsed>1 );
percentSort(p->a, p->nUsed);
p->bSorted = 1;
}
ix = p->rPct*(p->nUsed-1);
i1 = (unsigned)ix;
i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
v1 = p->a[i1];
v2 = p->a[i2];
vx = v1 + (v2-v1)*(ix-i1);
if( pFunc->bDiscrete ){
vx = p->a[i1];
}else{
i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
v1 = p->a[i1];
v2 = p->a[i2];
vx = v1 + (v2-v1)*(ix-i1);
}
sqlite3_result_double(pCtx, vx);
}
sqlite3_free(p->a);
memset(p, 0, sizeof(*p));
if( bIsFinal ){
sqlite3_free(p->a);
memset(p, 0, sizeof(*p));
}else{
p->bKeepSorted = 1;
}
}
static void percentFinal(sqlite3_context *pCtx){
percentCompute(pCtx, 1);
}
static void percentValue(sqlite3_context *pCtx){
percentCompute(pCtx, 0);
}
#ifdef _WIN32
#if defined(_WIN32) && !defined(SQLITE3_H) && !defined(SQLITE_STATIC_PERCENTILE)
__declspec(dllexport)
#endif
int sqlite3_percentile_init(
@@ -270,20 +483,21 @@ int sqlite3_percentile_init(
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
unsigned int i;
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
(void)pApi; /* Unused parameter */
#else
SQLITE_EXTENSION_INIT2(pApi);
#endif
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "percentile", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
0, percentStep, percentFinal);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "median", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
0, percentStep, percentFinal);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "percentile_cont", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS, &percentStep,
0, percentStep, percentFinal);
for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
rc = sqlite3_create_window_function(db,
aPercentFunc[i].zName,
aPercentFunc[i].nArg,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_SELFORDER1,
(void*)&aPercentFunc[i],
percentStep, percentFinal, percentValue, percentInverse, 0);
if( rc ) break;
}
return rc;
}
+44 -43
View File
@@ -42,6 +42,10 @@
# build the SQLite library and testing tools.
################################################################################
# If OPTIONS... is specified on the command-line, append its value to OPTS
#
OPTS += $(OPTIONS)
# This is how we compile
#
TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
@@ -537,6 +541,7 @@ FUZZSRC += $(TOP)/test/vt02.c
FUZZSRC += $(TOP)/test/fuzzinvariants.c
FUZZSRC += $(TOP)/ext/recover/dbdata.c
FUZZSRC += $(TOP)/ext/recover/sqlite3recover.c
FUZZSRC += $(TOP)/ext/misc/percentile.c
FUZZSRC += $(TOP)/ext/misc/randomjson.c
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
@@ -760,6 +765,7 @@ SHELL_DEP = \
$(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/memtrace.c \
$(TOP)/ext/misc/pcachetrace.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/shathree.c \
@@ -958,9 +964,14 @@ tcltest: ./testfixture$(EXE)
testrunner: testfixture$(EXE)
./testfixture$(EXE) $(TOP)/test/testrunner.tcl
# Runs both fuzztest and testrunner, consecutively.
# This is the testing target preferred by the core SQLite developers.
# It runs tests under a standard configuration, regardless of how
# ./configure was run. The devs run "make devtest" prior to each
# check-in, at a minimum. Probably other tests too, but at least this
# one.
#
devtest: testfixture$(EXE) fuzztest testrunner
devtest: srctree-check sourcetest
tclsh $(TOP)/test/testrunner.tcl mdevtest
mdevtest:
tclsh $(TOP)/test/testrunner.tcl mdevtest
@@ -971,10 +982,19 @@ mdevtest:
quicktest: ./testfixture$(EXE)
./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)
# The default test case. Runs most of the faster standard TCL tests,
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
test: fuzztest sourcetest $(TESTPROGS) tcltest
# Validate that various generated files in the source tree
# are up-to-date.
#
srctree-check: $(TOP)/tool/srctree-check.tcl
tclsh $(TOP)/tool/srctree-check.tcl
# Try to run tests on whatever options are specified by the
# environment variables. The SQLite developers seldom use this target.
# Instead# they use "make devtest" which runs tests on a standard set of
# options regardless of how SQLite is configured. This "test"
# target is provided for legacy only.
#
test: fuzztest sourcetest $(TESTPROGS) tcltest
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
@@ -1112,41 +1132,22 @@ install: sqlite3 libsqlite3.a sqlite3.h
mv sqlite3.h /usr/include
clean:
rm -f *.o sqlite3 sqlite3.exe libsqlite3.a sqlite3.h opcodes.*
rm -f lemon lemon.exe lempar.c parse.* sqlite*.tar.gz
rm -f mkkeywordhash mkkeywordhash.exe keywordhash.h
rm -f $(PUBLISH)
rm -f *.da *.bb *.bbg gmon.out
rm -rf tsrc target_source
rm -f testloadext.dll libtestloadext.so
rm -f amalgamation-testfixture amalgamation-testfixture.exe
rm -f fts3-testfixture fts3-testfixture.exe
rm -f testfixture testfixture.exe
rm -f threadtest3 threadtest3.exe
rm -f LogEst LogEst.exe
rm -f fts3view fts3view.exe
rm -f rollback-test rollback-test.exe
rm -f showdb showdb.exe
rm -f showjournal showjournal.exe
rm -f showstat4 showstat4.exe
rm -f showwal showwal.exe
rm -f changeset changeset.exe
rm -f speedtest1 speedtest1.exe
rm -f wordcount wordcount.exe
rm -f rbu rbu.exe
rm -f srcck1 srcck1.exe
rm -f sqlite3.c sqlite3-*.c fts?amal.c tclsqlite3.c
rm -f sqlite3rc.h
rm -f shell.c sqlite3ext.h
rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
rm -f sqlite3_expert sqlite3_expert.exe
rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe
rm -f fuzzershell fuzzershell.exe
rm -f fuzzcheck fuzzcheck.exe
rm -f sessionfuzz
rm -f sqldiff sqldiff.exe
rm -f fts5.* fts5parse.*
rm -f lsm.h lsm1.c
rm -f threadtest5
rm -f src-verify
rm -f *.lo *.la *.o *.c *.h *.da *.bb *.bbg gmon.* *.rws sqlite3$(TEXE)
rm -rf .libs .deps tsrc libtool target_source testrunner_*
rm -f lemon$(BEXE) sqlite*.tar.gz
rm -f mkkeywordhash$(BEXE) mksourceid$(BEXE)
rm -f parse.* fts5parse.*
rm -rf tsrc .target_source testrunner_bld_* testdir*
rm -f tclsqlite3$(TEXE)
rm -f $(TESTPROGS) testrunner.*
rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
rm -f wordcount$(TEXE) changeset$(TEXE) version-info$(TEXE)
rm -f *.dll *.lib *.exp *.def *.pc *.vsix
rm -f sqlite3_analyzer$(TEXE)
rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
rm -f threadtest5$(TEXE)
rm -f src-verify has_tclsh*
distclean: clean
+49 -44
View File
@@ -1,12 +1,12 @@
C Remove\sredundant\s#ifdef\saccidentally\sinserted\sinto\smkkeywordhash.c
D 2024-08-26T14:20:20.876
C ADd\sSQLITE_USE_ONLY_WIN32\sto\sthe\sDefault\sconfiguration\sfor\stesting\son\nWindows.\s\sTake\sit\soff\sof\sStdcall.
D 2024-09-03T17:01:07.501
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 101cb90f75c16ca3f8e7088364322441f9b01d6fdcef4a9c7f5fdcf78a3601a4
F Makefile.in af5fbc3453b745daa68c7aa5dfdb945c09cb724971db3b783d6b5e1a62279e28
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc 6c3fe8b6ce60e73f34a148c957d78b4648745c8d30e792423aa1a8d8bf12d065
F README.md 3d47ef5758e2de29d6f4e1aca714d51424baba86c8b561fef330f6ef2dc9282c
F Makefile.msc 2c905f4c795a628d7fd892294e8fdec6d5f719fa5b252cb839fed147e64435a0
F README.md 5b678e264236788390d11991f2c0052bd73f19790173883fc56d638bcb849154
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -17,7 +17,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am adedc1324b6a87fdd1265ddd336d2fb7d4f36a0e77b86ea553ae7cc4ea239347
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
F autoconf/Makefile.msc 7ac6c331fc3b8aa57b6782db995b8c0e49230352decd4e2662fd07c06a9ed623
F autoconf/Makefile.msc 2aced6442addab13ed115696eba28d9ed29caa3dd604a31392c2c7a5da301492
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
@@ -53,8 +53,8 @@ F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
F ext/consio/console_io.c b4885dfea71ed583315de8f0792a29d5fc7c7460b4a26c0aebe5cda5da8b38f8 x
F ext/consio/console_io.h 0548b83d7c4b7270ad544a67f2bb90cebc519637fa39b1838df4744cf0d87646
F ext/consio/console_io.c d2b74afae8d301de2e8447b1045fcd33eb59df13bf581d906d99c74fe5d2b13f x
F ext/consio/console_io.h b5ebe34aa15b357621ebbea3d3f2e2b24750d4280b5802516409e23947fd9ee5
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
F ext/expert/expert1.test 661f873fd451127edf822ef0d520088faa319135f6a15bd10be6801ac284ac9b
@@ -92,17 +92,17 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl 63db9624ccf70d4887836c320eda93ab552f21008f3be7ede551eac3ead62baa
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
F ext/fts5/fts5.h c72759fd15179934f10b71ae51ee999e8558f696335e4ec2d049243b764354ee
F ext/fts5/fts5.h efaaac0df3d3bc740383044c144b582f47921aafa21d7b10eb98f42c24c740b0
F ext/fts5/fts5Int.h 26a71a09cefa4ef6b4516b204ed48da3e1380970a19b3482eea7c5d805655360
F ext/fts5/fts5_aux.c 65a0468dd177d6093aa9ae1622e6d86b0136b8d267c62c0ad6493ad1e9a3d759
F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70673cb6f09
F ext/fts5/fts5_config.c 353d2a0d12678cae6ab5b9ce54aed8dac0825667b69248b5a4ed81cbefc109ea
F ext/fts5/fts5_expr.c 9a56f53700d1860f0ee2f373c2b9074eaf2a7aa0637d0e27a6476de26a3fee33
F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
F ext/fts5/fts5_index.c eb9a0dda3bc6ef969a6be8d2746af56856e67251810ddba08622b45be8477abe
F ext/fts5/fts5_main.c 3d8b778f65fe5be218f6a8e4019048f092c0c09621b035ce3e8804093036b578
F ext/fts5/fts5_index.c 571483823193f09439356741669aa8c81da838ae6f5e1bfa7517f7ee2fb3addd
F ext/fts5/fts5_main.c 1fddb53f495425d9314c74b30c5848a9dd254be0e5f445bfe38292d5ab21c288
F ext/fts5/fts5_storage.c 9a9b880be12901f1962ae2a5a7e1b74348b3099a1e728764e419f75d98e3e612
F ext/fts5/fts5_tcl.c 1dcf08028141c40a32634bdcf2d5601622ce4edc48f82ac4ce0cbe0a92a6961d
F ext/fts5/fts5_tcl.c 4db9258a7882c5eac0da4433042132aaf15b87dd1e1636c7a6ca203abd2c8bfe
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
F ext/fts5/fts5_tokenize.c ae9c4fa93174ef06ffc138bd4280a1c37f7e13624d3d2706aad4b80573f23c41
@@ -148,11 +148,12 @@ F ext/fts5/test/fts5contentless4.test ec34dc69ef474ca9997dae6d91e072906e0e9a5a4b
F ext/fts5/test/fts5contentless5.test 40cdcb4fe751672450829c5a96bd32c25fc2f6076279dd2ce5c58ac9a390132a
F ext/fts5/test/fts5corrupt.test 6485f721b88ba355ca5d701e7ee87a4efa3ea578d8e6adb26f51ef956c8328bd
F ext/fts5/test/fts5corrupt2.test 335911e3f68b9625d850325f9e29a128db3f4276a8c9d4e32134580da8f924c4
F ext/fts5/test/fts5corrupt3.test 621e9bca3e7299f487e1b29ff4179d9fc9560f5847dfc5b50a16010c9d2a0e5f
F ext/fts5/test/fts5corrupt3.test 4fc3bf129f1616bea00884a23fd9d7b0e46d01791d2b57fe8d68ac36e8d3ff7c
F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93f68f7d7a0d7d7dd733
F ext/fts5/test/fts5corrupt5.test 11b47126f5772cc37b67e3e8b2ed05895c4d07c05338bc07e4eea225bfe32c76
F ext/fts5/test/fts5corrupt6.test 2d72db743db7b5d9c9a6d0cfef24d799ed1aa5e8192b66c40e871a37ed9eed06
F ext/fts5/test/fts5corrupt7.test 4e830875c33b9ea3c4cf1ba71e692b63893cbb4faae8c69b1071889dc26e211c
F ext/fts5/test/fts5corrupt8.test b81d802e41631e98100f49a1aadeeffef860e30a62d6ed7d743c2797c477239e
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
@@ -164,7 +165,7 @@ F ext/fts5/test/fts5expr.test c7e208813df7a90badc856fde3796da79569b39382e0fdb430
F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd
F ext/fts5/test/fts5fault2.test 69c8fdbef830cd0d450908d4504d5bb86609e255af99c421c20a0756251fe344
F ext/fts5/test/fts5fault3.test da2f9e3e56ff5740d68ebdd6877c97089e7ed28ddff28a0da87a6afea27e5522
F ext/fts5/test/fts5fault4.test 87a10d0caee57da587c7588b0c8d25d2930197399b4812ad1e4d574c75324cee
F ext/fts5/test/fts5fault4.test a5c0e849127c24e1751bc453a817f09a1b8d460e75f9ae4764017e216a870db3
F ext/fts5/test/fts5fault5.test a336e4e11847de24c9497f80cce18e00bb3fab7fb11f97d04eb9af898900a762
F ext/fts5/test/fts5fault6.test 40f49976c6ca8927bf7d65d0b8df46009d7ea172e1d4050b294610e7ea0a2979
F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd164090be139e9e97ed4c
@@ -177,12 +178,13 @@ F ext/fts5/test/fts5faultE.test 844586ce71dab4be85bb86880e87b624d089f851654cd22e
F ext/fts5/test/fts5faultF.test 4abef99f86e99d9f0c6460dd68c586a766b6b9f1f660ada55bf2e8266bd1bbc1
F ext/fts5/test/fts5faultG.test 0544411ffcb3e19b42866f757a8a5e0fb8fef3a62c06f61d14deebc571bb7ea9
F ext/fts5/test/fts5faultH.test 2b2b5b8cb1b3fd7679f488c06e22af44107fbc6137eaf45b3e771dc7b149312d
F ext/fts5/test/fts5faultI.test e1e8a927122a8c3be8614a59717e838cad0505ba0a6f404983da8430e7aeb14d
F ext/fts5/test/fts5faultI.test ae4b83ac953200bd7b66d53038f7d6a4fc29cd64831b8e1795538babcea7c638
F ext/fts5/test/fts5first.test bfd685b96905bf541d99d8644e0a7219d1d833455a08ab64e344071a613b6ba9
F ext/fts5/test/fts5full.test 97d263c1072f4a560929cca31e70f65d2ae232610e17e6affcf7e979df59547b
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
F ext/fts5/test/fts5hash.test fd3e0367fbf0b0944d6936fdb22696350f57b9871069c6766251578a103e8a14
F ext/fts5/test/fts5integrity.test 646796671205dae46af5bb12a49b5696483cfe8e12d71d21454940b13ace95ab
F ext/fts5/test/fts5integrity2.test 4c3636615c0201232c44a8105d5cb14fd5499fd0ee3014d7ffd7e83aac76ece8
F ext/fts5/test/fts5interrupt.test 20d04204d3e341b104c0c24a41596b6393a3a81eba1044c168db0e106f9ac92c
F ext/fts5/test/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400f8d2d27ea9373e0c4a1
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
@@ -191,7 +193,7 @@ F ext/fts5/test/fts5locale.test 797cf6f5e017462ab11313ce884b9f1df8ff063811e74ef4
F ext/fts5/test/fts5matchinfo.test 877520582feb86bbfd95ab780099bcba4526f18ac75ee34979144cf86ba3a5a3
F ext/fts5/test/fts5merge.test 2654df0bcdb2d117c2d38b6aeb0168061be01c643f9e9194b36c43a2970e8082
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
F ext/fts5/test/fts5misc.test 60bb2be4a2d83d7a45047c1812781e2e337a27efa539d86356ef7f4acaf08eab
F ext/fts5/test/fts5misc.test 8c3cc771f773dc4bb4973620c51e7729e324ca2cc80eb8894f1c2c605e361f0b
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
F ext/fts5/test/fts5near.test 33d60867581066e5db7016deb5d651628125d7ff4e0233a88175aa5b65874c74
@@ -225,7 +227,7 @@ F ext/fts5/test/fts5secure6.test 74bf04733cc523bccca519bb03d3b4e2ed6f6e3db7c59bf
F ext/fts5/test/fts5secure7.test fd03d0868d64340a1db8615b02e5508fea409de13910114e4f19eaefc120777a
F ext/fts5/test/fts5secure8.test 808ade9d172ed07b24b85c57dd53b6d2b1aba018b4e634d267ce572221de80e0
F ext/fts5/test/fts5securefault.test c34a28c7cd2f31a8b8907563889e1329a97da975c08df2d951422bcef8e2ebc5
F ext/fts5/test/fts5simple.test ed7c3815c9fa1c16166258cb98edb2e014c63c7589958d76c5487df0df913d61
F ext/fts5/test/fts5simple.test 302cdb4f8a3350b091f4f1bccd82d05610428657f6f9e81c17703ba48267ec40
F ext/fts5/test/fts5simple2.test d10d963a357b8ec77b99032e4c816459b4dbdb1f6eee25eada7ef3ed245cb2dc
F ext/fts5/test/fts5simple3.test 146ec3dc8f5763d6212641c9f0a2f1cba41679353d2add7b963beceb115dc7f4
F ext/fts5/test/fts5synonym.test becc8cea6cfc958a50b30c572c68cbfdf7455971d0fe988202ce67638d2c6cf6
@@ -409,7 +411,7 @@ F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58
F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0
F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
F ext/misc/percentile.c af1941dc87d45dd0c2698a3087fbfe9ee0d157e5e72da521430c4b784abcbe81
F ext/misc/percentile.c 42eb041edab407e512aaa087f99ed9287fe0b3224f7a6d194456c00fc1454312
F ext/misc/prefixes.c 82645f79229877afab08c8b08ca1e7fa31921280906b90a61c294e4f540cd2a6
F ext/misc/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47cc06c
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
@@ -684,7 +686,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk 9541ffdce424ddddb463e2480c3f1cb4067bbd3a6d2c84b3f083cb128a2fa721
F main.mk 5a2e7d4a852c058373efc78407816de41595d06975148c766092b3cf0fea4298
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -703,13 +705,13 @@ F src/auth.c 4c1ea890e0069ad73bead5d17a5b12c34cfa4f1a24175c8147ea439b64be271c
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
F src/btree.c 8b42fc7d9efdb2df05c30e8f91ff6cfbd979724ae24bf90269028468b7a13333
F src/btree.c 8c5592c618741c5fc9733e7efe3927bfafad3e999d15b0a0f3f1d3f3e17b919e
F src/btree.h 55066f513eb095db935169dab1dc2f7c7a747ef223c533f5d4ad4dfed346cbd0
F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
F src/build.c 3a1840d9d171ce2d24f4c1f7acda7266ab796c664290c1acba65ff98ce2bd01e
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 64e4b1227b4ed123146f0aa2989131d1fbd9b927b11e80c9d58c6a68f9cd5ce3
F src/ctime.c b224d3db0f28c4a5f1407c50107a0a8133bd244ff3c7f6f8cedeb896a8cf1b64
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
@@ -717,7 +719,7 @@ F src/delete.c 444c4d1eaac40103461e3b6f0881846dd3aafc1cec1dd169d3482fa331667da7
F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c 1f61e32e7a357e615b5d2e774bee563761fce4f2fd97ecb0f72c33e62a2ada5f
F src/func.c df400a1d3f4625997d4dd8a81951c303e066277c29b861d37e03cd152d7858dd
F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
@@ -727,7 +729,7 @@ F src/insert.c f8d1a0f8ee258411009c6b7f2d93170e351bd19f5ad89d57e1180644297cbe70
F src/json.c 5b6a1d6015997b9ee848a32948720bdb26a0ef2de5a2127ebf7355ce66dbdc0d
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
F src/main.c a520c325c7400b249242945f2c602acb19662c40f5db1c04d88664cfaa8b85ac
F src/main.c e7b53893f9fb3ad76baa8513f85c167b34d5c8e25ce64608db440f5637d0fe9e
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -753,7 +755,7 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
F src/parse.y f4c8ded81b05059c284bc9512aaa07f6ecd29add585e35d53d72a67894b6e4d7
F src/parse.y a7a8d42eeff01d267444ddb476029b0b1726fb70ae3d77984140f17ad02e2d61
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
@@ -765,11 +767,11 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 2c127880c0634962837f16f2f48a295e514357af959330cc038de73015d5b5e8
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4b14337a2742f0c0beeba490e9a05507e9b4b12184b9cd12773501d08d48e3fe
F src/shell.c.in 5a05e1a1d187ab916afe9a628d7e9b20b5997273b595bd748db324814e0ccca9
F src/sqlite.h.in f07bff4225a1244efd604a0ffef81ed69f29d3dbaed7e22f906f26229ba3ca9e
F src/shell.c.in 40de636c1d90fb8a9ca7f49dc8f50d930f1b60736e73aca5eb37c4c7d0e47f9d
F src/sqlite.h.in 77f55bd1978a04a14db211732f0a609077cf60ba4ccf9baf39988f508945419c
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
F src/sqliteInt.h 28c878bdf528879afefe1994ac007d094f8061f2fdacdc55d6055d7e9341151e
F src/sqliteInt.h 889cd632f4386bbd8619b166abb7d25f1c8ce6514e90cb7f22f63bd530fc6107
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -789,7 +791,7 @@ F src/test_backup.c bd901e3c116c7f3b3bbbd4aae4ce87d99b400c9cbb0a9e7b4610af451d97
F src/test_bestindex.c 3401bee51665cbf7f9ed2552b5795452a8b86365e4c9ece745b54155a55670c6
F src/test_blob.c bcdf6a6c22d0bcc13c41479d63692ef413add2a4d30e1e26b9f74ab85b9fb4d5
F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5
F src/test_config.c 46eaf39842cace9d540aeefb50fe24dd3204a622893a97952cbb49c20b2f8b21
F src/test_config.c 345b8e383f71cecc36d0fa05f2f06639c254b188f98101c3c97749df43037086
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
@@ -827,20 +829,20 @@ F src/test_windirent.h da2e5b73c32d09905fbdd00f27cd802212a32a58ead882736fe4f5eb7
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 6fac7f14dd021fecfdd8be93c27937804c4b665d2da9e667a10e4b5f04c6e085
F src/tokenize.c 3f703cacdab728d7741e5a6ac242006d74fe1c2754d4f03ed889d7253259bd68
F src/treeview.c 88aa39b754f5ef7214385c1bbbdd2f3dc20efafeed0cf590e8d1199b9c6e44aa
F src/trigger.c 0bb986a5b96047fd597c6aac28588853df56064e576e6b81ba777ef2ccaac461
F src/update.c 0e01aa6a3edf9ec112b33eb714b9016a81241497b1fb7c3e74332f4f71756508
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
F src/util.c 5d1a0134cf4240648d1c6bb5cc8efaca0ea2b5d5c840985aec7e947271f04375
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
F src/vacuum.c b763b6457bd058d2072ef9364832351fd8d11e8abf70cbb349657360f7d55c40
F src/vdbe.c be5f58bc29f60252e041a618eae59e8d57d460ba136c5403cf0abf955560c457
F src/vdbe.h c2549a215898a390de6669cfa32adba56f0d7e17ba5a7f7b14506d6fd5f0c36a
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
F src/vdbeapi.c 80235ac380e9467fec1cb0883354d841f2a771976e766995f7e0c77f845406df
F src/vdbeaux.c 25d685cafe119ff890c94345e884ea558a6b5d823bfa52ba708eb8ff3c70aa71
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
F src/vdbeblob.c 255be187436da38b01f276c02e6a08103489bbe2a7c6c21537b7aecbe0e1f797
F src/vdbemem.c 831a244831eaa45335f9ae276b50a7a82ee10d8c46c2c72492d4eb8c98d94d89
F src/vdbesort.c d0a3c7056c081703c8b6d91ad60f17da5e062a5c64bf568ed0fa1b5f4cae311f
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
@@ -1265,7 +1267,7 @@ F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce3
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c 6e87c27df3d95c556870187987dff6efdc712b5cea60abedc8ab9215f471907a
F test/fuzzcheck.c 20be6c96bd0da2e91d25f089a037c1b3f8142211c97104f20629bf15610019e6
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1516,7 +1518,7 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463
F test/percentile.test 74e383216a075251512d6ba98beb9dccd6da465e3f73817fc438379e3a628de7
F test/percentile.test 52ba89d6ee6b65f770972b67dace358bab7cdbd532803d3db157845268e789cd
F test/permutations.test 405542f1d659942994a6b38a9e024cf5cfd23eaa68c806aeb24a72d7c9186e80
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test 11cb9310c42f921918f7f563e3c0b6e70f9f9c3a6a1cf12af8fccb6c574f3882
@@ -1625,10 +1627,10 @@ F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 490bf9d0c7c9564fea318c46d49369f4690b825b584c9a544dbdccf61bc0babc
F test/shell2.test 56da24128304c9ab67da2964cc80beff7b35761c446ec6e6e98bff2775b15026
F test/shell2.test 01a01f76ed98088ce598794fbf5b359e148271541a8ddbf79d21cc353cc67a24
F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8
F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
F test/shell5.test bafa4c0b67b7a8027e729970a625c9225cb7ef854acc4e52624c45074faaaddf
F test/shell5.test 0e5f8ce08206b9998a778cfe1989e20e47839153c05af2da29198150172e22fc
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
F test/shell8.test aea51ecbcd4494c746b096aeff51d841d04d5f0dc4b62eb42427f16109b87acd
@@ -1713,8 +1715,8 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 2c203a2dd664298f239f0ec3ce22fbc65b5f021c1e09edbae8452af8a694e052
F test/testrunner.tcl 5d02deeba7a53baeadae6aa7641d90aac58fdfa3a7bcac85cfcfd752b1aab87c
F test/testrunner_data.tcl c5ae2b1f9a99210b0600d002fb3af1fee350997cee9416551e83b93501360ebf
F test/testrunner.tcl d117492b6ec7293f7906dd4ff48135dd9801bdf42db0f48f88b3328867aa94ff
F test/testrunner_data.tcl 9a85a86fd5f9a1a94102b246203aa7c3e047623b8bb5decde7789cfd959580b1
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -2069,7 +2071,7 @@ F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af
F test/windowB.test aad7c31739999f68a98a813cfd78390918fc70f56d2d925317a1523cab548ecf
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
F test/windowD.test 65cf5a765fb8072450e8a0de2979ce7f09a38d87724fe1280c6444073e3da49b
F test/windowE.test c98507e0b0d95980ad25845db758557757be2d7054198ccf522c7d277057a3df
F test/windowE.test d045a5fbaaf50ecac9483e1249dd317ba4f9d189c405a730ba6effdefb87b94f
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
@@ -2130,8 +2132,8 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl 060e9785e9503bf51f8b1b11b542bdeef90fd0ceb0738154f6762acec0c61e5f x
F tool/mkkeywordhash.c 8a0a0401a6e0f01ca6e02f58b294a813d067554474875f4fe0222c2b8b0d6ed3
F tool/mkctimec.tcl e3af51acc2ef92062fe6d622de010a27a34b497258a248dada04388b916c61c6 x
F tool/mkkeywordhash.c 6b0be901c47f9ad42215fc995eb2f4384ac49213b1fba395102ec3e999acf559
F tool/mkmsvcmin.tcl d76c45efda1cce2d4005bcea7b8a22bb752e3256009f331120fb4fecb14ebb7a
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
@@ -2148,7 +2150,7 @@ F tool/mktoolzip.tcl c7a9b685f5131d755e7d941cec50cee7f34178b9e34c9a89811eeb08617
F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e540a
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
F tool/omittest.tcl e99c9fecc3f7a8ca2fa75d8ec8bdbb5acce33dc69f0c280aae53064693387f65
F tool/omittest.tcl 5ca5e4e01716d5f35b48b00fd351d929f01fbb98169a5a3cd00baf3d2e2019a9
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
F tool/replace.tcl 511c61acfe563dfb58675efb4628bb158a13d48ff8322123ac447e9d25a82d9a
@@ -2210,8 +2212,11 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 16d32676e2e98a7710787de16850c328e7519e893f81ed56f6155a8fa9cbc3a4
R a100ff1c9bda3fc624920cd66e34ae7c
P dcbebe30f594a99e23b5ccd8d199b92118204a3e52e75c78d98c394601252e81
R dad5ee3b909b00a448aebb3a7771c6ec
T *branch * new-win32-test-config
T *sym-new-win32-test-config *
T -sym-trunk *
U drh
Z 58c98d8befdb125e16f0435abf5b1a98
Z 5378530d857d88d300d11bbd793c3a45
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
b08f3b74495e125f92c8968472fc8028c73d8df5400195df3081e3d8df8bd985
8ace3f15e4f7e8249bf4cf558ceecdf67792bb7801529ef86b4d36363bb8ff8c
+1 -1
View File
@@ -5989,7 +5989,7 @@ int sqlite3BtreeIndexMoveto(
&& indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
&& pIdxKey->errCode==SQLITE_OK
){
pCur->curFlags &= ~BTCF_ValidOvfl;
pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
if( !pCur->pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
+3
View File
@@ -295,6 +295,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
"ENABLE_OFFSET_SQL_FUNC",
#endif
#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
"ENABLE_ORDERED_SET_AGGREGATES",
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK",
#endif
+6 -2
View File
@@ -2049,7 +2049,11 @@ static void minMaxFinalize(sqlite3_context *context){
** group_concat(EXPR, ?SEPARATOR?)
** string_agg(EXPR, SEPARATOR)
**
** The SEPARATOR goes before the EXPR string. This is tragic. The
** Content is accumulated in GroupConcatCtx.str with the SEPARATOR
** coming before the EXPR value, except for the first entry which
** omits the SEPARATOR.
**
** It is tragic that the SEPARATOR goes before the EXPR string. The
** groupConcatInverse() implementation would have been easier if the
** SEPARATOR were appended after EXPR. And the order is undocumented,
** so we could change it, in theory. But the old behavior has been
@@ -2153,7 +2157,7 @@ static void groupConcatInverse(
/* pGCC is always non-NULL since groupConcatStep() will have always
** run first to initialize it */
if( ALWAYS(pGCC) ){
int nVS;
int nVS; /* Number of characters to remove */
/* Must call sqlite3_value_text() to convert the argument into text prior
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
(void)sqlite3_value_text(argv[0]);
+2 -1
View File
@@ -1926,7 +1926,8 @@ int sqlite3CreateFunc(
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE);
SQLITE_SUBTYPE|SQLITE_INNOCUOUS|
SQLITE_RESULT_SUBTYPE|SQLITE_SELFORDER1);
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
/* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But
+111 -232
View File
@@ -264,11 +264,14 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
EXCLUDE GROUPS OTHERS TIES
%endif SQLITE_OMIT_WINDOWFUNC
%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
WITHIN
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
%ifndef SQLITE_OMIT_GENERATED_COLUMNS
GENERATED ALWAYS
%endif
MATERIALIZED
REINDEX RENAME CTIME_KW IF AGGREGATE
REINDEX RENAME CTIME_KW IF
.
%wildcard ANY.
@@ -295,8 +298,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
%left CONCAT PTR.
%left COLLATE.
%right BITNOT.
%nonassoc ON FROM.
%nonassoc JOIN_KW JOIN.
%nonassoc ON.
// An IDENTIFIER can be a generic identifier, or one of several
// keywords. Any non-standard keyword can also be an identifier.
@@ -625,233 +627,6 @@ oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
}
%endif
%ifndef SQLITE_OMIT_SUBQUERY
%include {
SQLITE_NOINLINE SrcList *sqlite3SrcListAppendSubFrom(
Parse *pParse, /* Parsing context */
SrcList *pFrom, /* LHS of the FROM clause */
SrcList *pSubFrom, /* New parenthesized sub-FROM to append */
Token *pAs, /* AS-Name of the sub-FROM */
OnOrUsing *pOnUsing /* ON or USING clause associated with the join */
){
if( pFrom==0 && pAs->n==0 && pOnUsing->pOn==0 && pOnUsing->pUsing==0 ){
pFrom = pSubFrom;
}else if( ALWAYS(pSubFrom!=0) && pSubFrom->nSrc==1 ){
pFrom = sqlite3SrcListAppendFromTerm(pParse,pFrom,0,0,pAs,0,pOnUsing);
if( pFrom ){
SrcItem *pNew = &pFrom->a[pFrom->nSrc-1];
SrcItem *pOld = pSubFrom->a;
assert( pOld->fg.fixedSchema==0 );
pNew->zName = pOld->zName;
assert( pOld->fg.fixedSchema==0 );
if( pOld->fg.isSubquery ){
pNew->fg.isSubquery = 1;
pNew->u4.pSubq = pOld->u4.pSubq;
pOld->u4.pSubq = 0;
pOld->fg.isSubquery = 0;
assert( pNew->u4.pSubq!=0 && pNew->u4.pSubq->pSelect!=0 );
if( (pNew->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 ){
pNew->fg.isNestedFrom = 1;
}
}else{
pNew->u4.zDatabase = pOld->u4.zDatabase;
pOld->u4.zDatabase = 0;
}
if( pOld->fg.isTabFunc ){
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
pOld->u1.pFuncArg = 0;
pOld->fg.isTabFunc = 0;
pNew->fg.isTabFunc = 1;
}
pOld->zName = 0;
}
sqlite3SrcListDelete(pParse->db, pSubFrom);
}else{
Select *pSubquery;
sqlite3SrcListShiftJoinType(pParse,pSubFrom);
pSubquery = sqlite3SelectNew(pParse,0,pSubFrom,0,0,0,0,SF_NestedFrom,0);
pFrom = sqlite3SrcListAppendFromTerm(pParse,pFrom,0,0,pAs,pSubquery,pOnUsing);
}
return pFrom;
}
}
%endif SQLITE_OMIT_SUBQUERY
%ifndef SQLITE_OMIT_FROM_FIRST
%include {
/* The Pipe object represents a pipe under construction. It is a transient
** object found only on the LALR(1) parser stack. */
typedef struct Pipe Pipe;
struct Pipe {
SrcList *pFrom; /* The FROM clause */
ExprList *pProj; /* The projection - list of columns to return */
ExprList *pOrderBy; /* The ORDER BY clause */
ExprList *pGroupBy; /* The GROUP BY clause */
Expr *pLimit; /* The LIMIT or LIMIT/OFFSET clause */
Expr *pWhere; /* The WHERE clause */
Expr *pHaving; /* The HAVING clause */
int selFlags; /* SF_DISTINCT or SF_ALL or 0 */
u8 bSeenAgg; /* True if AGGREGATE has been seen */
u8 bNeedPush; /* PipePush needed before adding terms to pProj */
Token sAs; /* Value of a pending AS clause */
};
/* Delete a pipe object */
void sqlite3PipeDelete(sqlite3 *db, Pipe *p){
sqlite3SrcListDelete(db, p->pFrom);
sqlite3ExprListDelete(db, p->pProj);
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprListDelete(db, p->pGroupBy);
sqlite3ExprDelete(db, p->pLimit);
sqlite3ExprDelete(db, p->pWhere);
sqlite3ExprDelete(db, p->pHaving);
sqlite3DbFree(db, p);
}
/* Generate a Select from the current content of a Pipe. Reset the Pipe
** to be empty, except do not remove the AS token if there is one and do
** not delete the Pipe.
*/
Select *sqlite3SelectFromPipe(Parse *pParse, Pipe *p){
Token sAs = p->sAs;
Select *pSel = sqlite3SelectNew(pParse, p->pProj, p->pFrom, p->pWhere,
p->pGroupBy, p->pHaving, p->pOrderBy,
p->selFlags, p->pLimit);
memset(p, 0, sizeof(*p));
p->sAs = sAs;
return pSel;
}
/* Take the current content of the pipe and make it "FROM <subquery>" pipe.
*/
void sqlite3PipePush(Parse *pParse, Pipe *pPipe, int jointype){
Select *pSel = sqlite3SelectFromPipe(pParse, pPipe);
SrcList *pFrom = pPipe->pFrom;
if( pFrom ) pFrom->a[pFrom->nSrc-1].fg.jointype = jointype;
pPipe->pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&pPipe->sAs,pSel,0);
pPipe->sAs.z = 0;
}
}
%type pipeline {Pipe*}
%destructor pipeline {sqlite3PipeDelete(pParse->db,$$);}
oneselect(A) ::= pipeline(X). {
Pipe *pPipe = X;
Select *pSel = sqlite3SelectFromPipe(pParse,pPipe);
sqlite3DbFree(pParse->db, pPipe);
A = pSel; /*A-overwrites-X */
}
pipeline(A) ::= FROM seltablist(X). {
Pipe *pPipe = sqlite3DbMallocZero(pParse->db, sizeof(*pPipe));
A = pPipe;
if( pPipe ){
pPipe->pFrom = X;
}else{
sqlite3SrcListDelete(pParse->db, X);
}
}
pipeline(A) ::= pipeline(A) pipe pipejoinop(J) nm(Y) dbnm(D) as(Z) on_using(N). {
Pipe *p = A;
if( p->bNeedPush ) sqlite3PipePush(pParse, p, J);
p->pFrom = sqlite3SrcListAppendFromTerm(pParse, p->pFrom, &Y, &D, &Z, 0, &N);
}
pipeline(A) ::= pipeline(A) pipe
pipejoinop(J) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) on_using(N). {
Pipe *p = A;
if( p->bNeedPush ) sqlite3PipePush(pParse, p, J);
p->pFrom = sqlite3SrcListAppendFromTerm(pParse, p->pFrom, &Y, &D, &Z, 0, &N);
sqlite3SrcListFuncArgs(pParse, p->pFrom, E);
}
pipeline(A) ::= pipeline(A) pipe pipejoinop(J) LP select(S) RP as(Z) on_using(N). {
Pipe *p = A;
if( p->bNeedPush ) sqlite3PipePush(pParse, p, J);
p->pFrom = sqlite3SrcListAppendFromTerm(pParse,p->pFrom,0,0,&Z,S,&N);
}
pipeline(A) ::= pipeline(A) pipe pipejoinop(J) LP seltablist(F) RP as(Z) on_using(N).{
Pipe *p = A;
if( p->bNeedPush ) sqlite3PipePush(pParse, p, J);
p->pFrom = sqlite3SrcListAppendSubFrom(pParse,p->pFrom,F,&Z,&N);
}
pipeline(A) ::= pipeline(A) pipe WHERE expr(W). {
Pipe *p = A;
if( p->bSeenAgg ){
p->pHaving = sqlite3ExprAnd(pParse, A->pHaving, W);
}else{
p->pWhere = sqlite3ExprAnd(pParse, A->pWhere, W);
}
p->bNeedPush = 1;
}
pipeline(A) ::= pipeline(A) pipe HAVING expr(W). {
Pipe *p = A;
p->pHaving = sqlite3ExprAnd(pParse, A->pHaving, W);
p->bNeedPush = 1;
}
pipeline(A) ::= pipeline(A) pipe AGGREGATE selcollist(W) groupby_opt(G). {
Pipe *p = A;
ExprList *pProj = W;
ExprList *pGroupby = G;
if( p->pProj ) sqlite3PipePush(pParse, p, 0);
if( pGroupby ){
int i;
for(i=0; i<pGroupby->nExpr; i++){
pProj = sqlite3ExprListAppend(pParse, pProj,
sqlite3ExprDup(pParse->db, pGroupby->a[i].pExpr, 0));
}
p->pGroupBy = pGroupby;
}
p->pProj = pProj;
p->bSeenAgg = 1;
p->bNeedPush = 1;
}
pipeline(A) ::= pipeline(A) pipe SELECT distinct(D) selcollist(W). {
Pipe *p = A;
if( p->pProj ) sqlite3PipePush(pParse, p, 0);
p->pProj = W;
p->selFlags = D;
p->bNeedPush = 1;
}
pipeline(A) ::= pipeline(A) pipe ORDER BY sortlist(X). {
Pipe *p = A;
if( p->pOrderBy || p->pLimit ) sqlite3PipePush(pParse, p, 0);
p->pOrderBy = X;
p->bNeedPush = 1;
}
pipeline(A) ::= pipeline(A) pipe LIMIT expr(X). {
Pipe *p = A;
Expr *pLimit = sqlite3PExpr(pParse,TK_LIMIT,X,0);
if( pLimit ){
sqlite3ExprDelete(pParse->db, p->pLimit);
p->pLimit = pLimit;
}
p->bNeedPush = 1;
}
pipeline(A) ::= pipeline(A) pipe LIMIT expr(X) OFFSET expr(Y). {
Pipe *p = A;
Expr *pLimit = sqlite3PExpr(pParse,TK_LIMIT,X,Y);
if( pLimit ){
sqlite3ExprDelete(pParse->db, p->pLimit);
p->pLimit = pLimit;
}
p->bNeedPush = 1;
}
pipeline(A) ::= pipeline(A) PIPE AS nm(X). {A->sAs = X; A->bNeedPush = 1;}
pipeline(A) ::= pipeline(A) pipe VIEW nm(X). {A->sAs = X; A->bNeedPush = 1;}
//pipeline ::= pipeline pipe DISTINCT ON nexprlist.
pipe ::= .
pipe ::= PIPE.
%type pipejoinop {int}
pipejoinop(X) ::= JOIN. { X = JT_INNER; }
pipejoinop(X) ::= JOIN_KW(A) JOIN.
{X = sqlite3JoinType(pParse,&A,0,0); /*X-overwrites-A*/}
pipejoinop(X) ::= JOIN_KW(A) nm(B) JOIN.
{X = sqlite3JoinType(pParse,&A,&B,0); /*X-overwrites-A*/}
pipejoinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN.
{X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/}
%endif FROM_first
// Single row VALUES clause.
//
@@ -961,7 +736,44 @@ seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) on_using(N
A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,&N);
}
seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP as(Z) on_using(N). {
A = sqlite3SrcListAppendSubFrom(pParse,A,F,&Z,&N);
if( A==0 && Z.n==0 && N.pOn==0 && N.pUsing==0 ){
A = F;
}else if( ALWAYS(F!=0) && F->nSrc==1 ){
A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,&N);
if( A ){
SrcItem *pNew = &A->a[A->nSrc-1];
SrcItem *pOld = F->a;
assert( pOld->fg.fixedSchema==0 );
pNew->zName = pOld->zName;
assert( pOld->fg.fixedSchema==0 );
if( pOld->fg.isSubquery ){
pNew->fg.isSubquery = 1;
pNew->u4.pSubq = pOld->u4.pSubq;
pOld->u4.pSubq = 0;
pOld->fg.isSubquery = 0;
assert( pNew->u4.pSubq!=0 && pNew->u4.pSubq->pSelect!=0 );
if( (pNew->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 ){
pNew->fg.isNestedFrom = 1;
}
}else{
pNew->u4.zDatabase = pOld->u4.zDatabase;
pOld->u4.zDatabase = 0;
}
if( pOld->fg.isTabFunc ){
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
pOld->u1.pFuncArg = 0;
pOld->fg.isTabFunc = 0;
pNew->fg.isTabFunc = 1;
}
pOld->zName = 0;
}
sqlite3SrcListDelete(pParse->db, F);
}else{
Select *pSubquery;
sqlite3SrcListShiftJoinType(pParse,F);
pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0);
A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,&N);
}
}
%endif SQLITE_OMIT_SUBQUERY
@@ -1370,6 +1182,65 @@ expr(A) ::= idj(X) LP STAR RP. {
A = sqlite3ExprFunction(pParse, 0, &X, 0);
}
%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
%include {
/* Generate an expression node that represents an ordered-set aggregate function.
**
** SQLite does not do anything special to evaluate ordered-set aggregates. The
** aggregate function itself is expected to do any required ordering on its own.
** This is just syntactic sugar.
**
** This syntax: percentile(f) WITHIN GROUP ( ORDER BY y )
**
** Is equivalent to: percentile(y,f)
**
** The purpose of this function is to generate an Expr node from the first syntax
** into a TK_FUNCTION node that looks like it came from the second syntax.
**
** Only functions that have the SQLITE_SELFORDER1 perperty are allowed to do this
** transformation. Because DISTINCT is not allowed in the ordered-set aggregate
** syntax, an error is raised if DISTINCT is used.
*/
static Expr *sqlite3ExprAddOrderedsetFunction(
Parse *pParse, /* Parsing context */
Token *pFuncname, /* Name of the function */
int isDistinct, /* DISTINCT or ALL qualifier */
ExprList *pOrig, /* Arguments to the function */
Expr *pOrderby /* Expression in the ORDER BY clause */
){
ExprList *p; /* Modified argument list */
Expr *pExpr; /* Final result */
p = sqlite3ExprListAppend(pParse, 0, pOrderby);
if( pOrig ){
int i;
for(i=0; i<pOrig->nExpr; i++){
p = sqlite3ExprListAppend(pParse, p, pOrig->a[i].pExpr);
pOrig->a[i].pExpr = 0;
}
sqlite3ExprListDelete(pParse->db, pOrig);
}
pExpr = sqlite3ExprFunction(pParse, p, pFuncname, 0);
if( pParse->nErr==0 ){
FuncDef *pDef;
u8 enc = ENC(pParse->db);
assert( pExpr!=0 ); /* Because otherwise pParse->nErr would not be zero */
assert( p!=0 ); /* Because otherwise pParse->nErr would not be zero */
pDef = sqlite3FindFunction(pParse->db, pExpr->u.zToken, -2, enc, 0);
if( pDef==0 || (pDef->funcFlags & SQLITE_SELFORDER1)==0 ){
sqlite3ErrorMsg(pParse, "%#T() is not an ordered-set aggregate", pExpr);
}else if( isDistinct==SF_Distinct ){
sqlite3ErrorMsg(pParse, "DISTINCT not allowed on ordered-set aggregate %T()",
pFuncname);
}
}
return pExpr;
}
}
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP WITHIN GROUP LP ORDER BY expr(E) RP. {
A = sqlite3ExprAddOrderedsetFunction(pParse, &X, D, Y, E);
}
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
%ifndef SQLITE_OMIT_WINDOWFUNC
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP filter_over(Z). {
A = sqlite3ExprFunction(pParse, Y, &X, D);
@@ -1384,7 +1255,15 @@ expr(A) ::= idj(X) LP STAR RP filter_over(Z). {
A = sqlite3ExprFunction(pParse, 0, &X, 0);
sqlite3WindowAttach(pParse, A, Z);
}
%endif
%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP WITHIN GROUP LP ORDER BY expr(E) RP
filter_over(Z). {
A = sqlite3ExprAddOrderedsetFunction(pParse, &X, D, Y, E);
sqlite3WindowAttach(pParse, A, Z);
}
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
%endif SQLITE_OMIT_WINDOWFUNC
term(A) ::= CTIME_KW(OP). {
A = sqlite3ExprFunction(pParse, 0, &OP, 0);
+3
View File
@@ -246,6 +246,7 @@ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
# define SQLITE_CIO_NO_CLASSIFY
# define SQLITE_CIO_NO_TRANSLATE
# define SQLITE_CIO_NO_SETMODE
# define SQLITE_CIO_NO_FLUSH
#endif
INCLUDE ../ext/consio/console_io.h
INCLUDE ../ext/consio/console_io.c
@@ -279,6 +280,7 @@ INCLUDE ../ext/consio/console_io.c
# define eputz(z) ePutsUtf8(z)
# define eputf ePrintfUtf8
# define oputb(buf,na) oPutbUtf8(buf,na)
# define fflush(s) fFlushBuffer(s);
#else
/* For Fiddle, all console handling and emit redirection is omitted. */
@@ -295,6 +297,7 @@ INCLUDE ../ext/consio/console_io.c
# define eputz(z) fputs(z,stderr)
# define sputz(fp,z) fputs(z,fp)
# define oputb(buf,na) fwrite(buf,1,na,stdout)
# undef fflush
#endif
/* True if the timer is enabled */
+10
View File
@@ -5615,6 +5615,15 @@ int sqlite3_create_window_function(
** [sqlite3_result_subtype()] should avoid setting this property, as the
** purpose of this property is to disable certain optimizations that are
** incompatible with subtypes.
**
** [[SQLITE_SELFORDER1]] <dt>SQLITE_SELFORDER1</dt><dd>
** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
** that internally orders the values provided to the first argument. The
** ordered-set aggregate SQL notation with a single ORDER BY term can be
** used to invoke this function. If the ordered-set aggregate notation is
** used on a function that lacks this flag, then an error is raised. Note
** that the ordered-set aggregate syntax is only available if SQLite is
** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
** </dd>
** </dl>
*/
@@ -5623,6 +5632,7 @@ int sqlite3_create_window_function(
#define SQLITE_SUBTYPE 0x000100000
#define SQLITE_INNOCUOUS 0x000200000
#define SQLITE_RESULT_SUBTYPE 0x001000000
#define SQLITE_SELFORDER1 0x002000000
/*
** CAPI3REF: Deprecated Functions
+2
View File
@@ -658,6 +658,8 @@
#ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite_int64
# define float sqlite_int64
# define fabs(X) ((X)<0?-(X):(X))
# define sqlite3IsOverflow(X) 0
# define LONGDOUBLE_TYPE sqlite_int64
# ifndef SQLITE_BIG_DBL
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
+16
View File
@@ -189,6 +189,14 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","0",TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
Tcl_SetVar2(interp, "sqlite_options",
"ordered_set_aggregates","1",TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options",
"ordered_set_aggregates","0",TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY);
#else
@@ -341,6 +349,14 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_ORDEREDSETFUNC
Tcl_SetVar2(interp, "sqlite_options", "ordered_set_funcs", "1",
TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "ordered_set_funcs", "0",
TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "1",
TCL_GLOBAL_ONLY);
+4 -9
View File
@@ -372,17 +372,12 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
}
case CC_PIPE: {
if( z[1]=='|' ){
*tokenType = TK_CONCAT;
return 2;
#ifdef TK_PIPE
}else if( z[1]=='>' ){
*tokenType = TK_PIPE;
return 2;
#endif
}else{
if( z[1]!='|' ){
*tokenType = TK_BITOR;
return 1;
}else{
*tokenType = TK_CONCAT;
return 2;
}
}
case CC_COMMA: {
+14 -9
View File
@@ -162,6 +162,9 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
const char *zDbMain; /* Schema name of database to vacuum */
const char *zOut; /* Name of output file */
u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */
u64 iRandom; /* Random value used for zDbVacuum[] */
char zDbVacuum[42]; /* Name of the ATTACH-ed database used for vacuum */
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
@@ -202,27 +205,29 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
pMain = db->aDb[iDb].pBt;
isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
/* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
** occurs anyway. The integrity of the database is maintained by a
** (possibly synchronous) transaction opened on the main database before
** sqlite3BtreeCopyFile() is called.
**
** An optimization would be to use a non-journaled pager.
** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but
** that actually made the VACUUM run slower. Very little journalling
** actually occurs when doing a vacuum since the vacuum_db is initially
** empty. Only the journal header is written. Apparently it takes more
** time to parse and run the PRAGMA to turn journalling off than it does
** to write the journal header file.
*/
sqlite3_randomness(sizeof(iRandom),&iRandom);
sqlite3_snprintf(sizeof(zDbVacuum), zDbVacuum, "vacuum_%016llx", iRandom);
nDb = db->nDb;
rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS %s", zOut, zDbVacuum);
db->openFlags = saved_openFlags;
if( rc!=SQLITE_OK ) goto end_of_vacuum;
assert( (db->nDb-1)==nDb );
pDb = &db->aDb[nDb];
assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
pTemp = pDb->pBt;
if( pOut ){
sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
@@ -299,11 +304,11 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
** the contents to the temporary database.
*/
rc = execSqlF(db, pzErrMsg,
"SELECT'INSERT INTO vacuum_db.'||quote(name)"
"SELECT'INSERT INTO %s.'||quote(name)"
"||' SELECT*FROM\"%w\".'||quote(name)"
"FROM vacuum_db.sqlite_schema "
"FROM %s.sqlite_schema "
"WHERE type='table'AND coalesce(rootpage,1)>0",
zDbMain
zDbVacuum, zDbMain, zDbVacuum
);
assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 );
db->mDbFlags &= ~DBFLAG_Vacuum;
@@ -315,11 +320,11 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
** from the schema table.
*/
rc = execSqlF(db, pzErrMsg,
"INSERT INTO vacuum_db.sqlite_schema"
"INSERT INTO %s.sqlite_schema"
" SELECT*FROM \"%w\".sqlite_schema"
" WHERE type IN('view','trigger')"
" OR(type='table'AND rootpage=0)",
zDbMain
zDbVacuum, zDbMain
);
if( rc ) goto end_of_vacuum;
+5
View File
@@ -167,6 +167,11 @@ int sqlite3_blob_open(
pTab = 0;
sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
}
if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){
pTab = 0;
sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s",
zTable);
}
#ifndef SQLITE_OMIT_VIEW
if( pTab && IsView(pTab) ){
pTab = 0;
+4 -2
View File
@@ -159,10 +159,11 @@ static struct GlobalVars {
} g;
/*
** Include the external vt02.c and randomjson.c modules.
** Include various extensions.
*/
extern int sqlite3_vt02_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_randomjson_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
/*
@@ -1329,7 +1330,8 @@ int runCombinedDbSqlInput(
/* Add the vt02 virtual table */
sqlite3_vt02_init(cx.db, 0, 0);
/* Add the random_json() and random_json5() functions */
/* Activate extensions */
sqlite3_percentile_init(cx.db, 0, 0);
sqlite3_randomjson_init(cx.db, 0, 0);
/* Add support for sqlite_dbdata and sqlite_dbptr virtual tables used
+425 -61
View File
@@ -9,7 +9,8 @@
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is percentile.c extension
# focus of this file is percentile.c extension. This also tests
# the SQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
#
set testdir [file dirname $argv0]
@@ -25,35 +26,65 @@ do_test percentile-1.0 {
}
execsql {SELECT percentile(x,0) FROM t1}
} {1.0}
foreach {in out} {
100 11.0
50 8.0
12.5 4.0
15 4.4
20 5.2
80 11.0
89 11.0
foreach {in out disc} {
100 11.0 11.0
50 8.0 8.0
12.5 4.0 4.0
15 4.4 4.0
20 5.2 4.0
80 11.0 11.0
89 11.0 11.0
} {
do_test percentile-1.1.$in {
do_test percentile-1.1.$in.1 {
execsql {SELECT percentile(x,$in) FROM t1}
} $out
do_test percentile-1.1.$in.2 {
execsql {SELECT percentile_cont(x,$in*0.01) FROM t1}
} $out
do_test percentile-1.1.$in.3 {
execsql {SELECT percentile_disc(x,$in*0.01) FROM t1}
} $disc
if {$in==50} {
do_test percentile-1.1.$in.4 {
execsql {SELECT median(x) FROM t1}
} $out
}
ifcapable ordered_set_aggregates {
do_test percentile-1.1.$in.5 {
execsql {SELECT percentile($in)WITHIN GROUP(ORDER BY x) FROM t1}
} $out
do_test percentile-1.1.$in.6 {
execsql {SELECT percentile_cont($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t1}
} $out
do_test percentile-1.1.$in.7 {
execsql {SELECT percentile_disc($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t1}
} $disc
if {$in==50} {
do_test percentile-1.1.$in.8 {
execsql {SELECT median() WITHIN GROUP (ORDER BY x) FROM t1}
} $out
}
}
}
do_execsql_test percentile-1.1.median {
SELECT median(x) FROM t1;
} 8.0
foreach {in out} {
1.0 11.0
0.5 8.0
0.125 4.0
0.15 4.4
0.2 5.2
0.8 11.0
0.89 11.0
} {
do_test percentile-1.1b-$in {
execsql {SELECT percentile_cont(x,$in) FROM t1}
} $out
ifcapable ordered_set_aggregates {
do_execsql_test percentile-1.1.median {
SELECT median() WITHIN GROUP (ORDER BY x) FROM t1;
} 8.0
do_execsql_test percentile-1.1.distinct.1 {
SELECT median(DISTINCT x) FROM t1;
} 7.0
do_catchsql_test percentile-1.1.distinct.2 {
SELECT percentile(DISTINCT 50) WITHIN GROUP (ORDER BY x) FROM t1;
} {1 {DISTINCT not allowed on ordered-set aggregate percentile()}}
} else {
do_catchsql_test percentile-1.1.median {
SELECT median() WITHIN GROUP (ORDER BY x) FROM t1;
} {1 {near "(": syntax error}}
}
# Add some NULL values.
@@ -61,28 +92,69 @@ foreach {in out} {
do_test percentile-1.2 {
execsql {INSERT INTO t1 VALUES(NULL),(NULL);}
} {}
foreach {in out} {
100 11.0
50 8.0
12.5 4.0
15 4.4
20 5.2
80 11.0
89 11.0
foreach {in out disc} {
100 11.0 11.0
50 8.0 8.0
12.5 4.0 4.0
15 4.4 4.0
20 5.2 4.0
80 11.0 11.0
89 11.0 11.0
} {
do_test percentile-1.3.$in {
do_test percentile-1.3.$in.1 {
execsql {SELECT percentile(x,$in) FROM t1}
} $out
do_test percentile-1.3.$in.2 {
execsql {SELECT percentile_cont(x,$in*0.01) FROM t1}
} $out
do_test percentile-1.3.$in.3 {
execsql {SELECT percentile_disc(x,$in*0.01) FROM t1}
} $disc
if {$in==50} {
do_test percentile-1.3.$in.4 {
execsql {SELECT median(x) FROM t1}
} $out
}
ifcapable ordered_set_aggregates {
do_test percentile-1.3.$in.5 {
execsql {SELECT percentile($in)WITHIN GROUP(ORDER BY x) FROM t1}
} $out
do_test percentile-1.3.$in.6 {
execsql {SELECT percentile_cont($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t1}
} $out
do_test percentile-1.3.$in.7 {
execsql {SELECT percentile_disc($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t1}
} $disc
if {$in==50} {
do_test percentile-1.3.$in.8 {
execsql {SELECT median() WITHIN GROUP (ORDER BY x) FROM t1}
} $out
}
}
}
# The second argument to percentile can change some, but not much.
#
do_test percentile-1.4 {
do_test percentile-1.4.1 {
catchsql {SELECT round(percentile(x, 15+0.000001*rowid),1) FROM t1}
} {0 4.4}
do_test percentile-1.5 {
catchsql {SELECT round(percentile(x, 15+0.1*rowid),1) FROM t1}
} {1 {2nd argument to percentile() is not the same for all input rows}}
do_test percentile-1.4.2 {
catchsql {SELECT round(percentile_cont(x,(15+0.000001*rowid)*0.01),1) FROM t1}
} {0 4.4}
do_test percentile-1.4.3 {
catchsql {SELECT percentile_disc(x, (15+0.000001*rowid)*0.01) FROM t1}
} {0 4.0}
do_test percentile-1.5.1 {
catchsql {SELECT percentile(x, 15+0.1*rowid) FROM t1}
} {1 {the fraction argument to percentile() is not the same for all input rows}}
do_test percentile-1.5.2 {
catchsql {SELECT percentile_cont(x, (15+0.1*rowid)*0.01) FROM t1}
} {1 {the fraction argument to percentile_cont() is not the same for all input rows}}
do_test percentile-1.5.3 {
catchsql {SELECT percentile_disc(x, (15+0.1*rowid)*0.01) FROM t1}
} {1 {the fraction argument to percentile_disc() is not the same for all input rows}}
# Input values in a random order
#
@@ -92,65 +164,152 @@ do_test percentile-1.6 {
INSERT INTO t2 SELECT x+0.0 FROM t1 ORDER BY random();
}
} {}
foreach {in out} {
100 11.0
50 8.0
12.5 4.0
15 4.4
20 5.2
80 11.0
89 11.0
foreach {in out disc} {
100 11.0 11.0
50 8.0 8.0
12.5 4.0 4.0
15 4.4 4.0
20 5.2 4.0
80 11.0 11.0
89 11.0 11.0
} {
do_test percentile-1.7.$in {
do_test percentile-1.7.$in.1 {
execsql {SELECT percentile(x,$in) FROM t2}
} $out
do_test percentile-1.7.$in.2 {
execsql {SELECT percentile_cont(x,$in*0.01) FROM t2}
} $out
do_test percentile-1.7.$in.3 {
execsql {SELECT percentile_disc(x,$in*0.01) FROM t2}
} $disc
if {$in==50} {
do_test percentile-1.7.$in.4 {
execsql {SELECT median(x) FROM t2}
} $out
}
ifcapable ordered_set_aggregates {
do_test percentile-1.7.$in.5 {
execsql {SELECT percentile($in)WITHIN GROUP(ORDER BY x) FROM t2}
} $out
do_test percentile-1.7.$in.6 {
execsql {SELECT percentile_cont($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t2}
} $out
do_test percentile-1.7.$in.7 {
execsql {SELECT percentile_disc($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t2}
} $disc
if {$in==50} {
do_test percentile-1.7.$in.8 {
execsql {SELECT median() WITHIN GROUP (ORDER BY x) FROM t2}
} $out
}
}
}
# Wrong number of arguments
#
do_test percentile-1.8 {
do_test percentile-1.8.1 {
catchsql {SELECT percentile(x,0,1) FROM t1}
} {1 {wrong number of arguments to function percentile()}}
do_test percentile-1.9 {
do_test percentile-1.8.2 {
catchsql {SELECT percentile_cont(x,0,1) FROM t1}
} {1 {wrong number of arguments to function percentile_cont()}}
do_test percentile-1.8.3 {
catchsql {SELECT percentile_disc(x,0,1) FROM t1}
} {1 {wrong number of arguments to function percentile_disc()}}
do_test percentile-1.8.4 {
catchsql {SELECT median(x,0) FROM t1}
} {1 {wrong number of arguments to function median()}}
ifcapable ordered_set_aggregates {
do_test percentile-1.8.5 {
catchsql {SELECT percentile(0,1) WITHIN GROUP(ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile()}}
do_test percentile-1.8.2 {
catchsql {SELECT percentile_cont(0,1)WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile_cont()}}
do_test percentile-1.8.3 {
catchsql {SELECT percentile_disc(0,1)WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile_disc()}}
do_test percentile-1.8.4 {
catchsql {SELECT median(x) WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function median()}}
}
do_test percentile-1.9.1 {
catchsql {SELECT percentile(x) FROM t1}
} {1 {wrong number of arguments to function percentile()}}
do_test percentile-1.9.2 {
catchsql {SELECT percentile_cont(x) FROM t1}
} {1 {wrong number of arguments to function percentile_cont()}}
do_test percentile-1.9.3 {
catchsql {SELECT percentile_disc(x) FROM t1}
} {1 {wrong number of arguments to function percentile_disc()}}
do_test percentile-1.9.4 {
catchsql {SELECT median() FROM t1}
} {1 {wrong number of arguments to function median()}}
ifcapable ordered_set_aggregates {
do_test percentile-1.9.5 {
catchsql {SELECT percentile() WITHIN GROUP(ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile()}}
do_test percentile-1.9.6 {
catchsql {SELECT percentile_cont()WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile_cont()}}
do_test percentile-1.9.7 {
catchsql {SELECT percentile_disc()WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile_disc()}}
}
# Second argument must be numeric
#
do_test percentile-1.10 {
catchsql {SELECT percentile(x,null) FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
do_test percentile-1.11 {
catchsql {SELECT percentile(x,'fifty') FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
do_test percentile-1.12 {
catchsql {SELECT percentile(x,x'3530') FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
do_test percentile-1.12b {
catchsql {SELECT percentile_cont(x,x'3530') FROM t1}
} {1 {2nd argument to percentile_cont() is not a number between 0.0 and 1.0}}
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
# Second argument is out of range
#
do_test percentile-1.13 {
catchsql {SELECT percentile(x,-0.0000001) FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
do_test percentile-1.14 {
catchsql {SELECT percentile(x,100.0000001) FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
do_test percentile-1.14b {
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
do_test percentile-1.14.2 {
catchsql {SELECT percentile_cont(x,1.0000001) FROM t1}
} {1 {2nd argument to percentile_cont() is not a number between 0.0 and 1.0}}
} {1 {the fraction argument to percentile_cont() is not between 0.0 and 1.0}}
do_test percentile-1.14.3 {
catchsql {SELECT percentile_disc(x,1.0000001) FROM t1}
} {1 {the fraction argument to percentile_disc() is not between 0.0 and 1.0}}
# First argument is not NULL and is not NUMERIC
#
do_test percentile-1.15 {
do_test percentile-1.15.1 {
catchsql {
BEGIN;
UPDATE t1 SET x='50' WHERE x IS NULL;
SELECT percentile(x, 50) FROM t1;
}
} {1 {1st argument to percentile() is not numeric}}
} {1 {input to percentile() is not numeric}}
do_test percentile-1.15.2 {
catchsql {
SELECT percentile_cont(x, 0.50) FROM t1;
}
} {1 {input to percentile_cont() is not numeric}}
do_test percentile-1.15.3 {
catchsql {
SELECT percentile_disc(x, 0.50) FROM t1;
}
} {1 {input to percentile_disc() is not numeric}}
do_test percentile-1.15.4 {
catchsql {
SELECT median(x) FROM t1;
}
} {1 {input to median() is not numeric}}
do_test percentile-1.16 {
catchsql {
ROLLBACK;
@@ -158,7 +317,7 @@ do_test percentile-1.16 {
UPDATE t1 SET x=x'3530' WHERE x IS NULL;
SELECT percentile(x, 50) FROM t1;
}
} {1 {1st argument to percentile() is not numeric}}
} {1 {input to percentile() is not numeric}}
do_test percentile-1.17 {
catchsql {
ROLLBACK;
@@ -186,7 +345,7 @@ do_test percentile-1.19 {
# Infinity as an input
#
do_test percentile-1.20 {
do_test percentile-1.20.1 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 SELECT x+0.0 FROM t2;
@@ -194,6 +353,43 @@ do_test percentile-1.20 {
SELECT percentile(x,50) from t1;
}
} {1 {Inf input to percentile()}}
do_test percentile-1.20.2 {
catchsql {
SELECT percentile_cont(x,0.50) from t1;
}
} {1 {Inf input to percentile_cont()}}
do_test percentile-1.20.3 {
catchsql {
SELECT percentile_disc(x,0.50) from t1;
}
} {1 {Inf input to percentile_disc()}}
do_test percentile-1.20.4 {
catchsql {
SELECT median(x) from t1;
}
} {1 {Inf input to median()}}
ifcapable ordered_set_aggregates {
do_test percentile-1.20.5 {
catchsql {
SELECT percentile(50) WITHIN GROUP (ORDER BY x) from t1;
}
} {1 {Inf input to percentile()}}
do_test percentile-1.20.6 {
catchsql {
SELECT percentile_cont(0.50) WITHIN GROUP (ORDER BY x) from t1;
}
} {1 {Inf input to percentile_cont()}}
do_test percentile-1.20.7 {
catchsql {
SELECT percentile_disc(0.50) WITHIN GROUP(ORDER BY X) from t1;
}
} {1 {Inf input to percentile_disc()}}
do_test percentile-1.20.8 {
catchsql {
SELECT median() WITHIN GROUP (ORDER BY x) from t1;
}
} {1 {Inf input to median()}}
}
do_test percentile-1.21 {
catchsql {
UPDATE t1 SET x=-1.0e300*1.0e300 WHERE rowid=5;
@@ -229,4 +425,172 @@ ifcapable vtab {
}
}
# median() as a window function. (2024-08-31)
#
do_execsql_test percentile-3.0 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
INSERT INTO t1 VALUES (1, 'A', 'one', 8.4),
(2, 'B', 'two', 7.1),
(3, 'C', 'three', 5.9),
(4, 'D', 'one', 11.0),
(5, 'E', 'two', 12.5),
(6, 'F', 'three', 0.0),
(7, 'G', 'one', 2.7);
}
foreach {id oba expr} {
1 0 "median(d)"
2 0 "percentile(d,50)"
3 0 "percentile_cont(d,0.5)"
4 1 "median() WITHIN GROUP (ORDER BY d)"
5 1 "percentile(50) WITHIN GROUP (ORDER BY d)"
6 1 "percentile_cont(0.5) WITHIN GROUP (ORDER BY d)"
} {
if {$oba} {
ifcapable !ordered_set_aggregates break
}
set sql "SELECT a, b, c, d, \
group_concat(b,'.') OVER w1 AS 'elements', \
$expr OVER w1 AS 'median' \
FROM t1 \
WINDOW w1 AS (ORDER BY c, a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)"
do_execsql_test percentile-3.$id.1 $sql {
1 A one 8.4 A.D 9.7
4 D one 11.0 A.D.G 8.4
7 G one 2.7 D.G.C 5.9
3 C three 5.9 G.C.F 2.7
6 F three 0.0 C.F.B 5.9
2 B two 7.1 F.B.E 7.1
5 E two 12.5 B.E 9.8
}
set sql "SELECT a, b, c, d, \
group_concat(b,'.') OVER w1 AS 'elements', \
$expr OVER w1 AS 'median' \
FROM t1 \
WINDOW w1 AS (ORDER BY c, a \
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING)"
do_execsql_test percentile-3.$id.2 $sql {
1 A one 8.4 A.D 9.7
4 D one 11.0 A.D.G 8.4
7 G one 2.7 A.D.G.C 7.15
3 C three 5.9 A.D.G.C.F 5.9
6 F three 0.0 A.D.G.C.F.B 6.5
2 B two 7.1 A.D.G.C.F.B.E 7.1
5 E two 12.5 A.D.G.C.F.B.E 7.1
}
set sql "SELECT a, b, c, d, \
group_concat(b,'.') OVER w1 AS 'elements', \
$expr OVER w1 AS 'median' \
FROM t1 \
WINDOW w1 AS (ORDER BY c, a \
ROWS BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING)"
do_execsql_test percentile-3.$id.3 $sql {
1 A one 8.4 A.D.G.C.F.B.E 7.1
4 D one 11.0 A.D.G.C.F.B.E 7.1
7 G one 2.7 D.G.C.F.B.E 6.5
3 C three 5.9 G.C.F.B.E 5.9
6 F three 0.0 C.F.B.E 6.5
2 B two 7.1 F.B.E 7.1
5 E two 12.5 B.E 9.8
}
}
# Test case adapted from examples shown at
# https://database.guide/3-functions-to-calculate-the-median-in-sql/
#
do_execsql_test percential-4.0 {
CREATE TABLE products(
vendorId INT,
productId INTEGER PRIMARY KEY,
productName REAL,
price REAL
);
INSERT INTO products VALUES
(1001, 17, 'Left-handed screwdriver', 25.99),
(1001, 49, 'Right-handed screwdriver', 25.99),
(1001, 216, 'Long weight (blue)', 14.75),
(1001, 31, 'Long weight (green)', 11.99),
(1002, 37, 'Sledge hammer', 33.49),
(1003, 7, 'Chainsaw', 245.00),
(1003, 8, 'Straw dog box', 55.99),
(1003, 12, 'Hammock', 11.01),
(1004, 113, 'Teapot', 12.45),
(1004, 117, 'Bottomless coffee mug', 9.99);
}
do_execsql_test percentile-4.1 {
SELECT VendorId, ProductId, /* ProductName,*/ Price,
avg(price) OVER (PARTITION BY vendorId) AS "Average",
median(price) OVER (PARTITION BY vendorId) AS "Median"
FROM products
ORDER BY vendorId, productId;
} {
1001 17 25.99 19.68 20.37
1001 31 11.99 19.68 20.37
1001 49 25.99 19.68 20.37
1001 216 14.75 19.68 20.37
1002 37 33.49 33.49 33.49
1003 7 245.0 104.0 55.99
1003 8 55.99 104.0 55.99
1003 12 11.01 104.0 55.99
1004 113 12.45 11.22 11.22
1004 117 9.99 11.22 11.22
}
do_execsql_test percentile-4.2 {
SELECT vendorId, median(price) FROM products
GROUP BY 1 ORDER BY 1;
} {1001 20.37 1002 33.49 1003 55.99 1004 11.22}
do_execsql_test percentile-5.0 {
CREATE TABLE user(name TEXT, class TEXT, cost REAL);
INSERT INTO user VALUES
('Alice', 'Y', 3578.27),
('Bob', 'X', 3399.99),
('Cindy', 'Z', 699.10),
('Dave', 'Y', 3078.27),
('Emma', 'Z', 2319.99),
('Fred', 'Y', 539.99),
('Gina', 'X', 2320.49),
('Hank', 'W', 24.99),
('Irma', 'W', 24.99),
('Jake', 'X', 2234.99),
('Kim', 'Y', 4319.99),
('Liam', 'X', 4968.59),
('Mia', 'W', 59.53),
('Nate', 'W', 23.50);
}
do_execsql_test percentile-5.1 {
SELECT name, class, cost,
percentile(cost, 0) OVER w1 AS 'P0',
percentile(cost, 25) OVER w1 AS 'P1',
percentile(cost, 50) OVER w1 AS 'P2',
percentile(cost, 75) OVER w1 AS 'P3',
percentile(cost, 100) OVER w1 AS 'P4'
FROM user
WINDOW w1 AS (PARTITION BY class)
ORDER BY class, cost;
} {
Nate W 23.5 23.5 24.6175 24.99 33.625 59.53
Hank W 24.99 23.5 24.6175 24.99 33.625 59.53
Irma W 24.99 23.5 24.6175 24.99 33.625 59.53
Mia W 59.53 23.5 24.6175 24.99 33.625 59.53
Jake X 2234.99 2234.99 2299.115 2860.24 3792.14 4968.59
Gina X 2320.49 2234.99 2299.115 2860.24 3792.14 4968.59
Bob X 3399.99 2234.99 2299.115 2860.24 3792.14 4968.59
Liam X 4968.59 2234.99 2299.115 2860.24 3792.14 4968.59
Fred Y 539.99 539.99 2443.7 3328.27 3763.7 4319.99
Dave Y 3078.27 539.99 2443.7 3328.27 3763.7 4319.99
Alice Y 3578.27 539.99 2443.7 3328.27 3763.7 4319.99
Kim Y 4319.99 539.99 2443.7 3328.27 3763.7 4319.99
Cindy Z 699.1 699.1 1104.3225 1509.545 1914.7675 2319.99
Emma Z 2319.99 699.1 1104.3225 1509.545 1914.7675 2319.99
}
# Fuzzer find.
do_execsql_test percentile-6.0 {
WITH RECURSIVE c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<12)
SELECT median(iif(n%2,0.1,1.0)) FROM c;
} 0.55
finish_test
+4
View File
@@ -217,6 +217,7 @@ do_test shell2-1.4.9 {
done
2}}
ifcapable vtab {
# Verify that generate_series stays sane near 64-bit range boundaries.
# See overflow report at https://sqlite.org/forum/forumpost/5d34ce5280
do_test shell2-1.4.10 {
@@ -247,7 +248,9 @@ do_test shell2-1.4.10 {
0
1
2}}
} ;# ifcapable vtab
ifcapable vtab {
# Bug discovered while messing around, .import hangs with
# bit 7 set in column separator.
do_test shell2-1.4.11 {
@@ -262,6 +265,7 @@ do_test shell2-1.4.11 {
.import dummy.csv t
SELECT count(*) FROM t;}]]
} {0 1}
} ;# ifcapable vtab
# Bug from forum post 7cbe081746dd3803
# Keywords as column names were producing an error message.
+8
View File
@@ -84,6 +84,14 @@ do_test shell5-1.4.1 {
.import FOO t1}]
} {1 {Error: cannot open "FOO"}}
# the remainder of these test cases require virtual tables.
#
ifcapable !vtab {
puts "Skipping subsequent tests due to SQLITE_OMIT_VIRTUALTABLE"
finish_test
return
}
# empty import file
do_test shell5-1.4.2 {
forcedelete shell5.csv
+160 -38
View File
@@ -54,7 +54,7 @@ proc usage {} {
Usage:
$a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?
$a0 PERMUTATION FILE
$a0 errors ?-v|--verbose?
$a0 errors ?-v|--verbose? ?-s|--summary? ?PATTERN?
$a0 help
$a0 njob ?NJOB?
$a0 script ?-msvc? CONFIG
@@ -89,7 +89,9 @@ Other PERMUTATION arguments must be run using testfixture, not tclsh:
If no PATTERN arguments are present, all tests specified by the PERMUTATION
are run. Otherwise, each pattern is interpreted as a glob pattern. Only
those tcl tests for which the final component of the filename matches at
least one specified pattern are run.
least one specified pattern are run. The glob wildcard '*' is prepended
to the pattern if it does not start with '^' and appended to every
pattern that does not end with '$'.
If no PATTERN arguments are present, then various fuzztest, threadtest
and other tests are run as part of the "release" permutation. These are
@@ -110,10 +112,12 @@ The "script" command outputs the script used to build a configuration.
Add the "-msvc" option for a Windows-compatible script. For a list of
available configurations enter "$a0 script help".
The "errors" commands shows the output of all tests that failed in the
The "errors" commands shows the output of tests that failed in the
most recent run. Complete output is shown if the -v or --verbose options
are used. Otherwise, an attempt is made to minimize the output to show
only the parts that contain the error messages.
only the parts that contain the error messages. The --summary option just
shows the jobs that failed. If PATTERN are provided, the error information
is only provided for jobs that match PATTERN.
Full documentation here: https://sqlite.org/src/doc/trunk/doc/testrunner.md
}]]
@@ -277,10 +281,12 @@ set TRG(schema) {
priority INTEGER NOT NULL, -- higher priority jobs may run earlier
/* Fields updated as jobs run */
starttime INTEGER,
endtime INTEGER,
starttime INTEGER, -- Start time (milliseconds since 1970)
endtime INTEGER, -- End time
state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ),
output TEXT
ntest INT, -- Number of test cases run
nerr INT, -- Number of errors reported
output TEXT -- test output
);
CREATE TABLE config(
@@ -352,8 +358,8 @@ if {([llength $argv]==2 || [llength $argv]==1)
sqlite3 mydb $TRG(dbname)
if {[llength $argv]==2} {
set param [lindex $argv 1]
if {[string is integer $param]==0 || $param<1 || $param>128} {
puts stderr "parameter must be an integer between 1 and 128"
if {[string is integer $param]==0 || $param<0 || $param>128} {
puts stderr "parameter must be an integer between 0 and 128"
exit 1
}
@@ -389,14 +395,36 @@ if {[string compare -nocase script [lindex $argv 0]]==0} {
exit
}
# Compute an elapse time string MM:SS or HH:MM:SS based on the
# number of milliseconds in the argument.
#
proc elapsetime {ms} {
set s [expr {int(($ms+500.0)*0.001)}]
set hr [expr {$s/3600}]
set mn [expr {($s/60)%60}]
set sc [expr {$s%60}]
if {$hr>0} {
return [format %02d:%02d:%02d $hr $mn $sc]
} else {
return [format %02d:%02d $mn $sc]
}
}
# Helper routine for show_status
#
proc display_job {jobdict {tm ""}} {
array set job $jobdict
set dfname [format %-60s $job(displayname)]
if {[string length $job(displayname)]>65} {
set dfname [format %.65s... $job(displayname)]
} else {
set dfname [format %-68s $job(displayname)]
}
set dtm ""
if {$tm!=""} {
set dtm [format %-10s "\[[expr {$tm-$job(starttime)}]ms\]"]
set dtm [expr {$tm-$job(starttime)}]
set dtm [format %8s [elapsetime $dtm]]
} else {
set dtm [format %8s ""]
}
puts " $dfname $dtm"
}
@@ -431,6 +459,11 @@ proc show_status {db cls} {
incr S($state) $cnt
incr total $cnt
}
set nt 0
set ne 0
$db eval {
SELECT sum(ntest) AS nt, sum(nerr) AS ne FROM jobs HAVING nt>0
} break
set fin [expr $S(done)+$S(failed)]
if {$cmdline!=""} {set cmdline " $cmdline"}
@@ -439,22 +472,25 @@ proc show_status {db cls} {
# overwrite.
puts -nonewline "\033\[H"
flush stdout
set clreol "\033\[K"
} else {
set clreol ""
}
set f ""
if {$S(failed)>0} {
set f "$S(failed) FAILED, "
}
puts "Command line: \[testrunner.tcl$cmdline\]$clreol"
puts "Jobs: $nJob "
puts "Summary: ${tm}ms, ($fin/$total) finished,\
${f}$S(running) running "
puts [format %-79.79s "Command: \[testrunner.tcl$cmdline\]"]
puts [format %-79.79s "Summary: [elapsetime $tm], $fin/$total jobs,\
$ne errors, $nt tests"]
set srcdir [file dirname [file dirname $TRG(info_script)]]
set line "Running: $S(running) (max: $nJob)"
if {$S(running)>0 && $fin>100 && $fin>0.05*$total} {
# Only estimate the time remaining after completing at least 100
# jobs amounting to 10% of the total. Never estimate less than
# 2% of the total time used so far.
set tmleft [expr {($tm/$fin)*($total-$fin)}]
if {$tmleft<0.02*$tm} {
set tmleft [expr {$tm*0.02}]
}
append line " est time left [elapsetime $tmleft]"
}
puts [format %-79.79s $line]
if {$S(running)>0} {
puts "Running: "
$db eval {
SELECT * FROM jobs WHERE state='running' ORDER BY starttime
} job {
@@ -462,15 +498,30 @@ proc show_status {db cls} {
}
}
if {$S(failed)>0} {
puts "Failures: "
# $toshow is the number of failures to report. In $cls mode,
# status tries to limit the number of failure reported so that
# the status display does not overflow a 24-line terminal. It will
# always show at least the most recent 4 failures, even if an overflow
# is needed. No limit is imposed for a status within $cls.
#
if {$cls && $S(failed)>18-$S(running)} {
set toshow [expr {18-$S(running)}]
if {$toshow<4} {set toshow 4}
set shown " (must recent $toshow shown)"
} else {
set toshow $S(failed)
set shown ""
}
puts [format %-79s "Failed: $S(failed) $shown"]
$db eval {
SELECT * FROM jobs WHERE state='failed' ORDER BY starttime
SELECT * FROM jobs WHERE state='failed'
ORDER BY endtime DESC LIMIT $toshow
} job {
display_job [array get job]
}
set nOmit [$db one {SELECT count(*) FROM jobs WHERE state='omit'}]
if {$nOmit} {
puts "$nOmit jobs omitted due to failures$clreol"
puts [format %-79s " ... $nOmit jobs omitted due to failures"]
}
}
if {$cls} {
@@ -557,15 +608,21 @@ proc aggregate_test_counts {db} {
#--------------------------------------------------------------------------
# Check if this is the "errors" command:
#
if {[llength $argv]>=1 && [llength $argv]<=2
if {[llength $argv]>=1
&& ([string compare -nocase errors [lindex $argv 0]]==0 ||
[string match err* [lindex $argv 0]]==1)
} {
set verbose 0
set pattern {}
set summary 0
for {set ii 1} {$ii<[llength $argv]} {incr ii} {
set a0 [lindex $argv $ii]
if {$a0=="-v" || $a0=="--verbose" || $a0=="-verbose"} {
set verbose 1
} elseif {$a0=="-s" || $a0=="--summary" || $a0=="-summary"} {
set summary 1
} elseif {$pattern==""} {
set pattern *[string trim $a0 *]*
} else {
puts "unknown option: \"$a0\"". Use --help for more info."
exit 1
@@ -573,9 +630,22 @@ if {[llength $argv]>=1 && [llength $argv]<=2
}
set cnt 0
sqlite3 mydb $TRG(dbname)
mydb timeout 2000
mydb eval {SELECT displaytype, displayname, output
FROM jobs WHERE state='failed'} {
mydb timeout 5000
if {$summary} {
set sql "SELECT displayname FROM jobs WHERE state='failed'"
} else {
set sql "SELECT displaytype, displayname, output FROM jobs \
WHERE state='failed'"
}
if {$pattern!=""} {
regsub -all {[^a-zA-Z0-9*/ ?]} $pattern . pattern
append sql " AND displayname GLOB '$pattern'"
}
mydb eval $sql {
if {$summary} {
puts "FAILED: $displayname"
continue
}
puts "**** $displayname ****"
if {$verbose || $displaytype!="tcl"} {
puts $output
@@ -588,9 +658,13 @@ if {[llength $argv]>=1 && [llength $argv]<=2
}
incr cnt
}
set summary [aggregate_test_counts mydb]
mydb close
puts "Total [lindex $summary 0] errors out of [lindex $summary 1] tests"
if {$pattern==""} {
set summary [aggregate_test_counts mydb]
mydb close
puts "Total [lindex $summary 0] errors out of [lindex $summary 1] tests"
} else {
mydb close
}
exit
}
@@ -842,7 +916,18 @@ proc add_tcl_jobs {build config patternlist {shelldepid ""}} {
if {[llength $patternlist]>0} {
set bMatch 0
foreach p $patternlist {
if {[string match $p [file tail $f]]} {
set p [string trim $p *]
if {[string index $p 0]=="^"} {
set p [string range $p 1 end]
} else {
set p "*$p"
}
if {[string index $p end]=="\$"} {
set p [string range $p 0 end-1]
} else {
set p "$p*"
}
if {[string match $p "$config [file tail $f]"]} {
set bMatch 1
break
}
@@ -1068,7 +1153,7 @@ proc add_jobs_from_cmdline {patternlist} {
if {[regexp "\\y$b\\y" $TRG(omitconfig)]} continue
set bld [add_build_job $b $TRG(testfixture)]
foreach c [trd_configs $TRG(platform) $b] {
add_tcl_jobs $bld $c $patternlist
add_tcl_jobs $bld $c $patternlist SHELL
}
if {$patternlist==""} {
@@ -1080,6 +1165,15 @@ proc add_jobs_from_cmdline {patternlist} {
}
}
}
if {[trdb one "SELECT EXISTS(SELECT 1
FROM jobs WHERE depid='SHELL')"]} {
set sbld [add_shell_build_job $b [lindex $bld 1] [lindex $bld 0]]
set sbldid [lindex $sbld 0]
trdb eval {
UPDATE jobs SET depid=$sbldid WHERE depid='SHELL'
}
}
}
}
@@ -1120,15 +1214,25 @@ proc make_new_testset {} {
}
proc mark_job_as_finished {jobid output state endtm} {
set ntest 1
set nerr 0
if {$endtm>0} {
if {[regexp {\y(\d+) errors out of (\d+) tests} $output all a b]} {
set nerr $a
set ntest $b
}
}
r_write_db {
if {$state=="failed"} {
set childstate omit
if {$nerr<=0} {set nerr 1}
} else {
set childstate ready
}
trdb eval {
UPDATE jobs
SET output=$output, state=$state, endtime=$endtm
SET output=$output, state=$state, endtime=$endtm,
ntest=$ntest, nerr=$nerr
WHERE jobid=$jobid;
UPDATE jobs SET state=$childstate WHERE depid=$jobid;
}
@@ -1371,6 +1475,17 @@ proc run_testset {} {
puts "\nTest database is $TRG(dbname)"
puts "Test log is $TRG(logname)"
trdb eval {
SELECT sum(ntest) AS totaltest,
sum(nerr) AS totalerr
FROM jobs
} break
trdb eval {
SELECT max(endtime)-min(starttime) AS totaltime
FROM jobs WHERE endtime>0
} break;
set et [elapsetime $totaltime]
puts "$totalerr errors out of $totaltest tests in about $et"
}
# Handle the --buildonly option, if it was specified.
@@ -1401,7 +1516,14 @@ proc explain_layer {indent depid} {
puts "${indent}$displayname in $dirname"
explain_layer "${indent} " $jobid
} elseif {$showtests} {
puts "${indent}[lindex $displayname end]"
set tail [lindex $displayname end]
set e1 [lindex $displayname 1]
if {[string match config=* $e1]} {
set cfg [string range $e1 7 end]
puts "${indent}($cfg) $tail"
} else {
puts "${indent}$tail"
}
}
}
}
@@ -1416,7 +1538,7 @@ if {$TRG(explain)} {
explain_tests
} else {
if {$TRG(nJob)>1} {
puts "splitting work across $TRG(nJob) jobs"
puts "splitting work across $TRG(nJob) cores"
}
puts "built testset in [expr $tm/1000]ms.."
handle_buildonly
+3 -5
View File
@@ -16,7 +16,6 @@ namespace eval trd {
set tcltest(linux.Have-Not) veryquick
set tcltest(linux.Secure-Delete) veryquick
set tcltest(linux.Unlock-Notify) veryquick
set tcltest(linux.User-Auth) veryquick
set tcltest(linux.Update-Delete-Limit) veryquick
set tcltest(linux.Extra-Robustness) veryquick
set tcltest(linux.Device-Two) veryquick
@@ -89,6 +88,8 @@ namespace eval trd {
--disable-amalgamation --disable-shared
--enable-session
-DSQLITE_ENABLE_RBU
-DSQLITE_ENABLE_STMT_SCANSTATUS
-DSQLITE_USE_ONLY_WIN32=1
}
# These two are used by [testrunner.tcl mdevtest] (All-O0) and
@@ -96,6 +97,7 @@ namespace eval trd {
#
set build(All-Debug) {
--enable-debug --enable-all
-DSQLITE_ENABLE_ORDERED_SET_AGGREGATES
}
set build(All-O0) {
-O0 --enable-all
@@ -139,10 +141,6 @@ namespace eval trd {
-DSQLITE_THREADSAFE
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
}
set build(User-Auth) {
-O2
-DSQLITE_USER_AUTHENTICATION=1
}
set build(Secure-Delete) {
-O2
-DSQLITE_SECURE_DELETE=1
+32
View File
@@ -73,6 +73,38 @@ do_catchsql_test 2.2 {
WINDOW w1 AS (PARTITION BY x OVER w1);
} {1 {near "OVER": syntax error}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
BEGIN TRANSACTION;
CREATE TABLE t2(c1 INT, c2 REAL);
INSERT INTO t2 VALUES
(447,0.0), (448,0.0), (449,0.0), (452,0.0), (453,0.0), (454,0.0), (455,0.0),
(456,0.0), (459,0.0), (460,0.0), (462,0.0), (463,0.0), (466,0.0), (467,0.0),
(468,0.0), (469,0.0), (470,0.0), (473,0.0), (474,0.0), (475,0.0), (476,0.0),
(477,0.0), (480,0.0), (481,0.0), (482,0.0), (483,0.0), (484,0.0), (487,0.0),
(488,0.0), (489,0.0), (490,0.0), (491,0.0), (494,0.0), (495,0.0), (496,0.0),
(497,0.0), (498,0.0), (501,0.0), (502,0.0), (503,0.0), (504,0.0), (505,0.0),
(508,0.0), (509,0.0), (510,0.0), (511,0.0), (512,0.0), (515,0.0), (516,0.0),
(517,0.0), (518,0.0), (519,0.0), (522,0.0), (523,0.0), (524,0.0), (525,0.0),
(526,0.0), (529,0.0), (530,0.0), (531,0.0), (532,0.0), (533,0.0), (536,0.0),
(537,1.0), (538,0.0), (539,0.0), (540,0.0), (543,0.0), (544,0.0);
COMMIT;
}
do_execsql_test 3.1 {
select c1, max(c2) over (order by c1 range 366.0 preceding) from t2;
} {
447 0.0 448 0.0 449 0.0 452 0.0 453 0.0 454 0.0 455 0.0 456 0.0 459 0.0
460 0.0 462 0.0 463 0.0 466 0.0 467 0.0 468 0.0 469 0.0 470 0.0 473 0.0
474 0.0 475 0.0 476 0.0 477 0.0 480 0.0 481 0.0 482 0.0 483 0.0 484 0.0
487 0.0 488 0.0 489 0.0 490 0.0 491 0.0 494 0.0 495 0.0 496 0.0 497 0.0
498 0.0 501 0.0 502 0.0 503 0.0 504 0.0 505 0.0 508 0.0 509 0.0 510 0.0
511 0.0 512 0.0 515 0.0 516 0.0 517 0.0 518 0.0 519 0.0 522 0.0 523 0.0
524 0.0 525 0.0 526 0.0 529 0.0 530 0.0 531 0.0 532 0.0 533 0.0 536 0.0
537 1.0 538 1.0 539 1.0 540 1.0 543 1.0 544 1.0
}
finish_test
+2
View File
@@ -159,6 +159,7 @@ set boolean_defnil_options {
SQLITE_ENABLE_MULTIPLEX
SQLITE_ENABLE_NORMALIZE
SQLITE_ENABLE_NULL_TRIM
SQLITE_ENABLE_ORDERED_SET_AGGREGATES
SQLITE_ENABLE_OFFSET_SQL_FUNC
SQLITE_ENABLE_OVERSIZE_CELL_CHECK
SQLITE_ENABLE_PREUPDATE_HOOK
@@ -448,6 +449,7 @@ if {[catch {set cfd [open $destfile w]}]!=0} {
puts stderr "File '$destfile' unwritable."
exit 1;
}
fconfigure $cfd -translation binary
puts $cfd $::headWarning;
puts $cfd $::headCode;
+4 -4
View File
@@ -164,10 +164,10 @@ struct Keyword {
#else
# define RETURNING 0x00400000
#endif
#ifdef SQLITE_OMIT_FROM_FIRST
# define PIPE 0
#ifndef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
# define ORDERSET 0
#else
# define PIPE 0x00800000
# define ORDERSET 0x00800000
#endif
@@ -179,7 +179,6 @@ static Keyword aKeywordTable[] = {
{ "ACTION", "TK_ACTION", FKEY, 0 },
{ "ADD", "TK_ADD", ALTER, 1 },
{ "AFTER", "TK_AFTER", TRIGGER, 0 },
{ "AGGREGATE", "TK_AGGREGATE", PIPE, 10 },
{ "ALL", "TK_ALL", ALWAYS, 0 },
{ "ALTER", "TK_ALTER", ALTER, 0 },
{ "ALWAYS", "TK_ALWAYS", GENCOL, 0 },
@@ -322,6 +321,7 @@ static Keyword aKeywordTable[] = {
{ "WHERE", "TK_WHERE", ALWAYS, 10 },
{ "WINDOW", "TK_WINDOW", WINDOWFUNC, 3 },
{ "WITH", "TK_WITH", CTE, 4 },
{ "WITHIN", "TK_WITHIN", ORDERSET, 1 },
{ "WITHOUT", "TK_WITHOUT", ALWAYS, 1 },
};
+201 -351
View File
@@ -1,370 +1,220 @@
# Documentation for this script. This may be output to stderr
#!/usr/bin/tclsh
#
# Documentation for this script. This may be output to
# if the script is invoked incorrectly.
#
set ::USAGE_MESSAGE {
This Tcl script is used to test the various compile time options
available for omitting code (the SQLITE_OMIT_xxx options). It
should be invoked as follows:
available for building SQLite, especially options taht omit
features (the SQLITE_OMIT_xxx options). It should be invoked as follows:
<script> ?test-symbol? ?-makefile PATH-TO-MAKEFILE? ?-skip_run?
./configure CFLAGS=-O0
tclsh test/omittest.tcl
The default value for ::MAKEFILE is "../Makefile.linux.gcc".
If -skip_run option is given then only the compile part is attempted.
This script builds the testfixture program and runs the SQLite test suite
once with each SQLITE_OMIT_ option defined and then once with all options
defined together. Each run is performed in a seperate directory created
as a sub-directory of the current directory by the script. The output
of the build is saved in <sub-directory>/build.log. The output of the
test-suite is saved in <sub-directory>/test.log.
Almost any SQLite makefile (except those generated by configure - see below)
should work. The following properties are required:
* The makefile should support the "testfixture" target.
* The makefile should support the "test" target.
* The makefile should support the variable "OPTS" as a way to pass
options from the make command line to lemon and the C compiler.
More precisely, the following two invocations must be supported:
$::MAKEBIN -f $::MAKEFILE testfixture OPTS="-DSQLITE_OMIT_ALTERTABLE=1"
$::MAKEBIN -f $::MAKEFILE test
Makefiles generated by the sqlite configure program cannot be used as
they do not respect the OPTS variable.
}
# Build a testfixture executable and run quick.test using it. The first
# parameter is the name of the directory to create and use to run the
# test in. The second parameter is a list of OMIT symbols to define
# when doing so. For example:
# List of all options to be tested.
#
# run_quick_test /tmp/testdir {SQLITE_OMIT_TRIGGER SQLITE_OMIT_VIEW}
#
#
proc run_quick_test {dir omit_symbol_list} {
# Compile the value of the OPTS Makefile variable.
set opts ""
if {$::tcl_platform(platform)=="windows"} {
append opts "OPTS += -DSQLITE_OS_WIN=1\n"
set target "testfixture.exe"
} else {
append opts "OPTS += -DSQLITE_OS_UNIX=1\n"
}
foreach sym $omit_symbol_list {
append opts "OPTS += -D${sym}=1\n"
}
set CompileOptionsToTest {
SQLITE_OMIT_ALTERTABLE
SQLITE_OMIT_ANALYZE
SQLITE_OMIT_ATTACH
SQLITE_OMIT_AUTHORIZATION
SQLITE_OMIT_AUTOINCREMENT
SQLITE_OMIT_AUTOINIT
SQLITE_OMIT_AUTOMATIC_INDEX
SQLITE_OMIT_AUTORESET
SQLITE_OMIT_AUTOVACUUM
SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS
SQLITE_OMIT_BETWEEN_OPTIMIZATION
SQLITE_OMIT_BLOB_LITERAL
SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA
SQLITE_OMIT_CAST
SQLITE_OMIT_CHECK
SQLITE_OMIT_COMPILEOPTION_DIAGS
SQLITE_OMIT_COMPLETE
SQLITE_OMIT_COMPOUND_SELECT
SQLITE_OMIT_CONFLICT_CLAUSE
SQLITE_OMIT_CTE
SQLITE_OMIT_DATETIME_FUNCS
SQLITE_OMIT_DECLTYPE
SQLITE_OMIT_DEPRECATED
SQLITE_OMIT_DESERIALIZE
SQLITE_OMIT_DISKIO
SQLITE_OMIT_EXPLAIN
SQLITE_OMIT_FLAG_PRAGMAS
SQLITE_OMIT_FLOATING_POINT
SQLITE_OMIT_FOREIGN_KEY
SQLITE_OMIT_GENERATED_COLUMNS
SQLITE_OMIT_GET_TABLE
SQLITE_OMIT_HEX_INTEGER
SQLITE_OMIT_INCRBLOB
SQLITE_OMIT_INTEGRITY_CHECK
SQLITE_OMIT_INTROSPECTION_PRAGMAS
SQLITE_OMIT_JSON
SQLITE_OMIT_LIKE_OPTIMIZATION
SQLITE_OMIT_LOAD_EXTENSION
SQLITE_OMIT_LOCALTIME
SQLITE_OMIT_LOOKASIDE
SQLITE_OMIT_MEMORYDB
SQLITE_OMIT_OR_OPTIMIZATION
SQLITE_OMIT_PAGER_PRAGMAS
SQLITE_OMIT_PARSER_TRACE
SQLITE_OMIT_POPEN
SQLITE_OMIT_PRAGMA
SQLITE_OMIT_PROGRESS_CALLBACK
SQLITE_OMIT_QUICKBALANCE
SQLITE_OMIT_RANDOMNESS
SQLITE_OMIT_REINDEX
SQLITE_OMIT_SCHEMA_PRAGMAS
SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
SQLITE_OMIT_SHARED_CACHE
SQLITE_OMIT_SHUTDOWN_DIRECTORIES
SQLITE_OMIT_SUBQUERY
SQLITE_OMIT_TCL_VARIABLE
SQLITE_OMIT_TEMPDB
SQLITE_OMIT_TEST_CONTROL
SQLITE_OMIT_TRACE
SQLITE_OMIT_TRIGGER
SQLITE_OMIT_TRUNCATE_OPTIMIZATION
SQLITE_OMIT_TWOSIZE_LOOKASIDE
SQLITE_OMIT_UPSERT
SQLITE_OMIT_UTF
SQLITE_OMIT_VACUUM
SQLITE_OMIT_VIEW
SQLITE_OMIT_VIRTUALTABLE
SQLITE_OMIT_WAL
SQLITE_OMIT_WINDOWFUNC
SQLITE_OMIT_WSD
SQLITE_OMIT_XFER_OPT
SQLITE_ALLOW_ROWID_IN_VIEW
SQLITE_DISABLE_DIRSYNC
SQLITE_DISABLE_FTS
SQLITE_DISABLE_INTRINSIC
SQLITE_DISABLE_LFS
SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
SQLITE_DISABLE_SKIPAHEAD_DISTINCT
SQLITE_ENABLE_API_ARMOR
SQLITE_ENABLE_ATOMIC_WRITE
SQLITE_ENABLE_BATCH_ATOMIC_WRITE
SQLITE_ENABLE_BYTECODE_VTAB
SQLITE_ENABLE_CEROD
SQLITE_ENABLE_COLUMN_METADATA
SQLITE_ENABLE_COLUMN_USED_MASK
SQLITE_ENABLE_COMMENTS
SQLITE_ENABLE_CORRUPT_PGNO
SQLITE_ENABLE_COSTMULT
SQLITE_ENABLE_CURSOR_HINTS
SQLITE_ENABLE_DBPAGE_VTAB
SQLITE_ENABLE_DBSTAT_VTAB
SQLITE_ENABLE_EXPENSIVE_ASSERT
SQLITE_ENABLE_EXPLAIN_COMMENTS
SQLITE_ENABLE_FTS
SQLITE_ENABLE_GEOPOLY
SQLITE_ENABLE_HIDDEN_COLUMNS
SQLITE_ENABLE_ICU
SQLITE_ENABLE_ICU_COLLATIONS
SQLITE_ENABLE_INTERNAL_FUNCTIONS
SQLITE_ENABLE_IOTRACE
SQLITE_ENABLE_LOAD_EXTENSION
SQLITE_ENABLE_LOCKING_STYLE
SQLITE_ENABLE_MATH_FUNCTIONS
SQLITE_ENABLE_MEMORY_MANAGEMENT
SQLITE_ENABLE_MEMSYS
SQLITE_ENABLE_MODULE_COMMENTS
SQLITE_ENABLE_MULTIPLEX
SQLITE_ENABLE_MULTITHREADED_CHECKS
SQLITE_ENABLE_NORMALIZE
SQLITE_ENABLE_NULL_TRIM
SQLITE_ENABLE_OFFSET_SQL_FUNC
SQLITE_ENABLE_OVERSIZE_CELL_CHECK
SQLITE_ENABLE_PREUPDATE_HOOK
SQLITE_ENABLE_QPSG
SQLITE_ENABLE_RBU
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_SELECTTRACE
SQLITE_ENABLE_SESSION
SQLITE_ENABLE_SETLK_TIMEOUT
SQLITE_ENABLE_SNAPSHOT
SQLITE_ENABLE_SORTER_MMAP
SQLITE_ENABLE_SORTER_REFERENCE
SQLITE_ENABLE_SORTER_REFERENCES
SQLITE_ENABLE_SQLLOG
SQLITE_ENABLE_STAT
SQLITE_ENABLE_STMT_SCANSTATUS
SQLITE_ENABLE_STMTVTAB
SQLITE_ENABLE_TREETRACE
SQLITE_ENABLE_UNKNOWN_FUNCTION
SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SQLITE_ENABLE_UNLOCK_NOTIFY
SQLITE_ENABLE_UPDATE_DELETE_LIMIT
SQLITE_ENABLE_URI_00_ERROR
SQLITE_ENABLE_VFSTRACE
SQLITE_ENABLE_WHERETRACE
SQLITE_ENABLE_ZIPVFS
}
# Create the directory and do the build. If an error occurs return
# early without attempting to run the test suite.
file mkdir $dir
puts -nonewline "Building $dir..."
flush stdout
catch {
file copy -force ./config.h $dir
file copy -force ./libtool $dir
}
set fd [open $::MAKEFILE]
set mkfile [read $fd]
close $fd
regsub {\ninclude} $mkfile "\n$opts\ninclude" mkfile
set fd [open $dir/makefile w]
puts $fd $mkfile
close $fd
set rc [catch {
exec $::MAKEBIN -C $dir -f makefile clean $::TARGET >& $dir/build.log
}]
if {$rc} {
puts "No good. See $dir/build.log."
return
} else {
puts "Ok"
}
# Create an empty file "$dir/sqlite3". This is to trick the makefile out
# of trying to build the sqlite shell. The sqlite shell won't build
# with some of the OMIT options (i.e OMIT_COMPLETE).
set sqlite3_dummy $dir/sqlite3
if {$::tcl_platform(platform)=="windows"} {
append sqlite3_dummy ".exe"
}
if {![file exists $sqlite3_dummy]} {
set wr [open $sqlite3_dummy w]
puts $wr "dummy"
close $wr
# Parse command-line options.
#
for {set i 0} {$i<[llength $argv]} {incr i} {
set arg [lindex $argv $i]
switch -- $arg {
-start -
--start {
incr i
set startat [lindex $argv $i]
}
}
}
if {$::SKIP_RUN} {
# puts "Skip testing $dir."
} else {
# Run the test suite.
puts -nonewline "Testing $dir..."
flush stdout
set rc [catch {
exec $::MAKEBIN -C $dir -f makefile test >& $dir/test.log
}]
if {$rc} {
puts "No good. See $dir/test.log."
# Additional options required for some settings.
#
set More(SQLITE_OMIT_DISKIO) {-DSQLITE_OMIT_WAL}
# Compile-time options for Mac only
#
set MacOnly(SQLITE_ENABLE_LOCKING_STYLE) 1
# Compile-time options that might fail, depending on what libraries
# are installed. Failures on these tests issue a warning, but testing
# continues.
#
set FailIsOk(SQLITE_ENABLE_ICU) 1
set FailIsOk(SQLITE_ENABLE_ICU_COLLATIONS) 1
file mkdir omittest
foreach sym $CompileOptionsToTest {
if {[info exists startat]} {
if {$startat==$sym} {
unset startat
} else {
puts "Ok"
continue
}
}
}
# This proc processes the command line options passed to this script.
# Currently the only option supported is "-makefile", default
# "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this
# option.
#
proc process_options {argv} {
set ::MAKEBIN make ;# Default value
if {$::tcl_platform(platform)=="windows"} {
set ::MAKEFILE ./Makefile ;# Default value on Windows
if {[info exists MacOnly($sym)] && $tcl_platform(os)!="Darwin"} {
continue
}
set logfile "omittest/$sym.log"
if {[info exists More($sym)]} {
append opts "OPT_FEATURE_FLAGS=-D$sym $More($sym)"
} else {
set ::MAKEFILE ./Makefile.linux-gcc ;# Default value
set opts OPT_FEATURE_FLAGS=-D$sym
}
set ::SKIP_RUN 1 ;# Default to attempt test
set ::TARGET testfixture ;# Default thing to build
for {set i 0} {$i < [llength $argv]} {incr i} {
switch -regexp -- [lindex $argv $i] {
-{1,2}makefile {
incr i
set ::MAKEFILE [lindex $argv $i]
}
-{1,2}nmake {
set ::MAKEBIN nmake
set ::MAKEFILE ./Makefile.msc
}
-{1,2}target {
incr i
set ::TARGET [lindex $argv $i]
}
-{1,2}skip_run {
set ::SKIP_RUN 1
}
-{1,2}run {
set ::SKIP_RUN 0
}
-{1,2}help {
puts $::USAGE_MESSAGE
exit
}
-.* {
puts stderr "Unknown option: [lindex $argv i]"
puts stderr $::USAGE_MESSAGE
exit 1
}
default {
if {[info exists ::SYMBOL]} {
puts stderr [string trim $::USAGE_MESSAGE]
exit -1
}
set ::SYMBOL [lindex $argv $i]
}
}
set ::MAKEFILE [file normalize $::MAKEFILE]
}
}
# Main routine.
#
proc main {argv} {
# List of SQLITE_OMIT_XXX symbols supported by SQLite.
set ::OMIT_SYMBOLS [list \
SQLITE_OMIT_ALTERTABLE \
SQLITE_OMIT_ANALYZE \
SQLITE_OMIT_ATTACH \
SQLITE_OMIT_AUTHORIZATION \
SQLITE_OMIT_AUTOINCREMENT \
SQLITE_OMIT_AUTOINIT \
SQLITE_OMIT_AUTOMATIC_INDEX \
SQLITE_OMIT_AUTORESET \
SQLITE_OMIT_AUTOVACUUM \
SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS \
SQLITE_OMIT_BETWEEN_OPTIMIZATION \
SQLITE_OMIT_BLOB_LITERAL \
SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA \
SQLITE_OMIT_CAST \
SQLITE_OMIT_CHECK \
SQLITE_OMIT_COMPILEOPTION_DIAGS \
SQLITE_OMIT_COMPLETE \
SQLITE_OMIT_COMPOUND_SELECT \
SQLITE_OMIT_CONFLICT_CLAUSE \
SQLITE_OMIT_CTE \
SQLITE_OMIT_DATETIME_FUNCS \
SQLITE_OMIT_DECLTYPE \
SQLITE_OMIT_DEPRECATED \
SQLITE_OMIT_DESERIALIZE \
SQLITE_OMIT_DISKIO \
SQLITE_OMIT_EXPLAIN \
SQLITE_OMIT_FLAG_PRAGMAS \
SQLITE_OMIT_FLOATING_POINT \
SQLITE_OMIT_FOREIGN_KEY \
SQLITE_OMIT_GENERATED_COLUMNS \
SQLITE_OMIT_GET_TABLE \
SQLITE_OMIT_HEX_INTEGER \
SQLITE_OMIT_INCRBLOB \
SQLITE_OMIT_INTEGRITY_CHECK \
SQLITE_OMIT_INTROSPECTION_PRAGMAS \
SQLITE_OMIT_JSON \
SQLITE_OMIT_LIKE_OPTIMIZATION \
SQLITE_OMIT_LOAD_EXTENSION \
SQLITE_OMIT_LOCALTIME \
SQLITE_OMIT_LOOKASIDE \
SQLITE_OMIT_MEMORYDB \
SQLITE_OMIT_OR_OPTIMIZATION \
SQLITE_OMIT_PAGER_PRAGMAS \
SQLITE_OMIT_PARSER_TRACE \
SQLITE_OMIT_POPEN \
SQLITE_OMIT_PRAGMA \
SQLITE_OMIT_PROGRESS_CALLBACK \
SQLITE_OMIT_QUICKBALANCE \
SQLITE_OMIT_RANDOMNESS \
SQLITE_OMIT_REINDEX \
SQLITE_OMIT_SCHEMA_PRAGMAS \
SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS \
SQLITE_OMIT_SHARED_CACHE \
SQLITE_OMIT_SHUTDOWN_DIRECTORIES \
SQLITE_OMIT_SUBQUERY \
SQLITE_OMIT_TCL_VARIABLE \
SQLITE_OMIT_TEMPDB \
SQLITE_OMIT_TEST_CONTROL \
SQLITE_OMIT_TRACE \
SQLITE_OMIT_TRIGGER \
SQLITE_OMIT_TRUNCATE_OPTIMIZATION \
SQLITE_OMIT_TWOSIZE_LOOKASIDE \
SQLITE_OMIT_UPSERT \
SQLITE_OMIT_UTF \
SQLITE_OMIT_VACUUM \
SQLITE_OMIT_VIEW \
SQLITE_OMIT_VIRTUALTABLE \
SQLITE_OMIT_WAL \
SQLITE_OMIT_WINDOWFUNC \
SQLITE_OMIT_WSD \
SQLITE_OMIT_XFER_OPT \
]
set ::ENABLE_SYMBOLS [list \
SQLITE_ALLOW_ROWID_IN_VIEW \
SQLITE_DISABLE_DIRSYNC \
SQLITE_DISABLE_FTS \
SQLITE_DISABLE_INTRINSIC \
SQLITE_DISABLE_LFS \
SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS \
SQLITE_DISABLE_SKIPAHEAD_DISTINCT \
SQLITE_ENABLE_API_ARMOR \
SQLITE_ENABLE_ATOMIC_WRITE \
SQLITE_ENABLE_BATCH_ATOMIC_WRITE \
SQLITE_ENABLE_BYTECODE_VTAB \
SQLITE_ENABLE_CEROD \
SQLITE_ENABLE_COLUMN_METADATA \
SQLITE_ENABLE_COLUMN_USED_MASK \
SQLITE_ENABLE_COMMENTS \
SQLITE_ENABLE_CORRUPT_PGNO \
SQLITE_ENABLE_COSTMULT \
SQLITE_ENABLE_CURSOR_HINTS \
SQLITE_ENABLE_DBPAGE_VTAB \
SQLITE_ENABLE_DBSTAT_VTAB \
SQLITE_ENABLE_EXPENSIVE_ASSERT \
SQLITE_ENABLE_EXPLAIN_COMMENTS \
SQLITE_ENABLE_FTS \
SQLITE_ENABLE_GEOPOLY \
SQLITE_ENABLE_HIDDEN_COLUMNS \
SQLITE_ENABLE_ICU \
SQLITE_ENABLE_ICU_COLLATIONS \
SQLITE_ENABLE_INTERNAL_FUNCTIONS \
SQLITE_ENABLE_IOTRACE \
SQLITE_ENABLE_LOAD_EXTENSION \
SQLITE_ENABLE_LOCKING_STYLE \
SQLITE_ENABLE_MATH_FUNCTIONS \
SQLITE_ENABLE_MEMORY_MANAGEMENT \
SQLITE_ENABLE_MEMSYS \
SQLITE_ENABLE_MODULE_COMMENTS \
SQLITE_ENABLE_MULTIPLEX \
SQLITE_ENABLE_MULTITHREADED_CHECKS \
SQLITE_ENABLE_NORMALIZE \
SQLITE_ENABLE_NULL_TRIM \
SQLITE_ENABLE_OFFSET_SQL_FUNC \
SQLITE_ENABLE_OVERSIZE_CELL_CHECK \
SQLITE_ENABLE_PREUPDATE_HOOK \
SQLITE_ENABLE_QPSG \
SQLITE_ENABLE_RBU \
SQLITE_ENABLE_RTREE \
SQLITE_ENABLE_SELECTTRACE \
SQLITE_ENABLE_SESSION \
SQLITE_ENABLE_SETLK_TIMEOUT \
SQLITE_ENABLE_SNAPSHOT \
SQLITE_ENABLE_SORTER_MMAP\
SQLITE_ENABLE_SORTER_REFERENCE \
SQLITE_ENABLE_SORTER_REFERENCES \
SQLITE_ENABLE_SQLLOG\
SQLITE_ENABLE_STAT \
SQLITE_ENABLE_STMT_SCANSTATUS \
SQLITE_ENABLE_STMTVTAB \
SQLITE_ENABLE_TREETRACE \
SQLITE_ENABLE_UNKNOWN_FUNCTION \
SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
SQLITE_ENABLE_UNLOCK_NOTIFY \
SQLITE_ENABLE_UPDATE_DELETE_LIMIT \
SQLITE_ENABLE_URI_00_ERROR \
SQLITE_ENABLE_VFSTRACE \
SQLITE_ENABLE_WHERETRACE \
SQLITE_ENABLE_ZIPVFS \
]
# Process any command line options.
process_options $argv
if {[info exists ::SYMBOL] } {
set sym $::SYMBOL
if {[lsearch $::OMIT_SYMBOLS $sym]<0 && [lsearch $::ENABLE_SYMBOLS $sym]<0} {
puts stderr "No such symbol: $sym"
exit -1
}
set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
run_quick_test $dirname $sym
} else {
# First try a test with all OMIT symbols except SQLITE_OMIT_FLOATING_POINT
# and SQLITE_OMIT_PRAGMA defined. The former doesn't work (causes segfaults)
# and the latter is currently incompatible with the test suite (this should
# be fixed, but it will be a lot of work).
set allsyms [list]
foreach s $::OMIT_SYMBOLS {
if {$s!="SQLITE_OMIT_FLOATING_POINT" && $s!="SQLITE_OMIT_PRAGMA"} {
lappend allsyms $s
}
}
run_quick_test test_OMIT_EVERYTHING $allsyms
# Now try one quick.test with each of the OMIT symbols defined. Included
# are the OMIT_FLOATING_POINT and OMIT_PRAGMA symbols, even though we
# know they will fail. It's good to be reminded of this from time to time.
foreach sym $::OMIT_SYMBOLS {
set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
run_quick_test $dirname $sym
}
# Try the ENABLE/DISABLE symbols one at a time.
# We don't do them all at once since some are conflicting.
foreach sym $::ENABLE_SYMBOLS {
set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
run_quick_test $dirname $sym
puts "make tidy sqlite3.lo $opts"
if {[catch {exec make tidy sqlite3.lo $opts >& $logfile}]} {
puts "BUILD FAILED: see $logfile for details"
if {[info exists FailIsOk($sym)]} {
set Failure($sym) 1
} else {
puts "Note: After fixes, continue the test using:\n"
puts " [info nameofexe] $argv0 --start $sym\n"
exit 1
}
}
}
main $argv
if {[llength [array names Failure]]>0} {
puts "BUILD FAILED on the following:"
foreach sym [array names Failure] {
puts " * $sym"
}
}