Compare commits

...

28 Commits

Author SHA1 Message Date
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
stephan 87ebadbf4e shell.c.in: use eputz/oputz() instead of eputf/oputf() where appropriate to avoid compilation errors in -std=c99 mode (namely wasm builds).
FossilOrigin-Name: 9ef8317faebc29d016bdf2e8c678fb21ca2cfa95272f1f18b461fcaf0e220ac5
2024-08-25 11:59:29 +00:00
drh cc902fd25e Fix harmless compiler warnings in fts5V2toV1Tokenize().
FossilOrigin-Name: df65d00f104f31741056686f2ba41ecb192c552012bffb17c2a8b5d4db058328
2024-08-24 20:05:59 +00:00
drh 306a8dcf3e Fix compiler warnings in the CLI detected by MSVC.
FossilOrigin-Name: 23ae505cbfde6dfd1dbb2216cf76c1e316b49f2ca84491a1aae28ad33f7777a9
2024-08-24 20:01:05 +00:00
drh 838d2d3078 Improved help message for the --enable-test-status configuration option.
Fix the build for when that option is omitted.

FossilOrigin-Name: b404a5fe3f0532f6d56b5e65c44a59379c17d175c21ac69a1f2ba8aadf453313
2024-08-24 19:06:52 +00:00
drh 1d5a12e6a5 New ./configure option --enable-test-status causes testrunner.tcl to be
run with the --status option for targets like mdevtest and releasetest.

FossilOrigin-Name: 9ca8513c26e54c97f2d3c6105c42144100044727f6fb4c28048f7cd7270dd35e
2024-08-24 19:02:33 +00:00
drh f9eff9052d Remove a term from an assert() that is no longer relevant.
FossilOrigin-Name: 8b4766252b80075354a6b1406c5430fe999a6490aa3e079893fcc682d88734f7
2024-08-24 18:42:39 +00:00
dan 58b08d7702 Avoid a stack overflow that could be caused by a recursively defined WINDOW() with a strategically embedded error.
FossilOrigin-Name: bada54bd6bf54190e40aa721b77081015957d204c7b6a9fdbe8c67bcf20798f8
2024-08-24 15:54:15 +00:00
drh 27095fc4a5 Ensure that the WhereLoop.u.btree.pOrderBy field added by the
order-by-subquery optimization [7a0cdc7edb704a88] is correctly
initialized.  dbsqlfuzz 437be171a98687082a31ea6efc2fd5c5d64481c8.

FossilOrigin-Name: b75f8b2252aefe7bb96fa237205a1a9dc88c46d9ec09bca7407e6c636b203e7e
2024-08-24 11:48:19 +00:00
stephan 7766c9943e Eliminate use of strcpy() in shell.c.in to squelch an unwarranted link-time warning on OpenBSD.
FossilOrigin-Name: 32e9bf7f972144eacbb2580151220bc4fc1cbcc8bcf586ffd8e10762abf75c7e
2024-08-23 21:20:50 +00:00
dan 789da35848 Fix a problem in the ext/fts5/extract_api_docs.tcl script.
FossilOrigin-Name: 9a9d0f6301faefe324261f03543023ffb6a90823349c6946abb0df2f69b31f96
2024-08-23 17:40:29 +00:00
dan 8d4edd0d67 Add fts5 auxiliary function fts5_get_locale(). For querying the locale of a stored value.
FossilOrigin-Name: 396f720f36a937145ac727c2750acfd26e4eda350b46d648d82a7e9985545a9f
2024-08-23 15:18:02 +00:00
drh 5804da0218 Enhance the generate_series() table-valued function such that it is able to
recognize equality and inequality constraints on the "value" column and
optimize its operating accordingly.

FossilOrigin-Name: d50b784807333c5461a2d027778c746c799285b95bb1952f142b317ea2846460
2024-08-22 18:12:10 +00:00
drh d55ab84451 Add the SQLITE_INDEX_SCAN_HEX bit to the sqlite3_index_info.idxFlags bitmask.
When set, this bit causes the EXPLAIN QUERY PLAN output to show the idxNum
value in hex rather than in decimal.  This is purely a debugging aid.

FossilOrigin-Name: 6c00e88ebdb41d6317bb8758825521614dedc2e6e6289ff415c5f0406eed815b
2024-08-22 16:22:08 +00:00
drh 889ce8ee90 Add SQLITE_TESTCTRL_GETOPT. Use it to implement improvements to the
".testctrl opt" dot-command in the CLI, and similar enhancements to TH3.

FossilOrigin-Name: 6500baa9914b08ce19c361a69f19a80e5d800fcb82579d1c1e03601c7a664338
2024-08-21 20:25:31 +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
30 changed files with 966 additions and 212 deletions
+8 -3
View File
@@ -117,6 +117,11 @@ HAVE_TCL = @HAVE_TCL@
#
TCLSH_CMD = @TCLSH_CMD@
# Additional options when running tests using testrunner.tcl
# This is usually either blank, or else --status
#
TSTRNNR_OPTS = @TSTRNNR_OPTS@
# Where do we want to install the tcl plugin
#
TCLLIBDIR = @TCLLIBDIR@
@@ -1363,10 +1368,10 @@ testrunner: testfixture$(TEXE)
devtest: srctree-check testfixture$(TEXE) fuzztest testrunner
mdevtest: srctree-check has_tclsh85
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS)
sdevtest: has_tclsh85
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl sdevtest
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl sdevtest $(TSTRNNR_OPTS)
# Validate that various generated files in the source tree
# are up-to-date.
@@ -1377,7 +1382,7 @@ srctree-check: $(TOP)/tool/srctree-check.tcl
# Testing for a release
#
releasetest: srctree-check testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl release
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
# Minimal testing that runs in less than 3 minutes
#
Vendored
+34 -14
View File
@@ -793,6 +793,7 @@ HAVE_WASI_SDK
RELEASE
VERSION
program_prefix
TSTRNNR_OPTS
TCLLIBDIR
HAVE_TCL
TCL_STUB_LIB_SPEC
@@ -889,6 +890,7 @@ enable_largefile
with_tclsh
with_tcl
enable_tcl
enable_test_status
with_wasi_sdk
enable_threadsafe
enable_releasemode
@@ -1546,6 +1548,7 @@ Optional Features:
--disable-largefile omit support for large files
--disable-tcl omit building accessory programs that require
TCL-dev
--enable-test-status Full-screen status of tests
--disable-threadsafe Disable mutexing
--enable-releasemode Support libtool link to release mode
--enable-tempstore Use an in-ram database for temporary tables
@@ -3939,13 +3942,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3942: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3945: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3945: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3948: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3948: output\"" >&5)
(eval echo "\"\$as_me:3951: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5151,7 +5154,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5154 "configure"' > conftest.$ac_ext
echo '#line 5157 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6676,11 +6679,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:6679: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6682: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6683: \$? = $ac_status" >&5
echo "$as_me:6686: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7015,11 +7018,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7018: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7021: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7022: \$? = $ac_status" >&5
echo "$as_me:7025: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7120,11 +7123,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7123: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7126: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7127: \$? = $ac_status" >&5
echo "$as_me:7130: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7175,11 +7178,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7178: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7181: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7182: \$? = $ac_status" >&5
echo "$as_me:7185: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9555,7 +9558,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9558 "configure"
#line 9561 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9651,7 +9654,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9654 "configure"
#line 9657 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10484,6 +10487,23 @@ if test "x${TCLLIBDIR+set}" != "xset" ; then
TCLLIBDIR="${TCLLIBDIR}/sqlite3"
fi
#########
# Set up options for running tests.
#
# Check whether --enable-test-status was given.
if test "${enable_test_status+set}" = set; then :
enableval=$enable_test_status; use_vt100=$enableval
else
use_vt100=no
fi
if test $use_vt100 != no; then
TSTRNNR_OPTS=--status
else
TSTRNNR_OPTS=
fi
#########
# Set up an appropriate program prefix
+12
View File
@@ -227,6 +227,18 @@ if test "x${TCLLIBDIR+set}" != "xset" ; then
TCLLIBDIR="${TCLLIBDIR}/sqlite3"
fi
#########
# Set up options for running tests.
#
AC_ARG_ENABLE(test-status, AS_HELP_STRING([--enable-test-status],[Full-screen status of tests]),
[use_vt100=$enableval],[use_vt100=no])
if test $use_vt100 != no; then
TSTRNNR_OPTS=--status
else
TSTRNNR_OPTS=
fi
AC_SUBST(TSTRNNR_OPTS)
#########
# Set up an appropriate program prefix
+82 -2
View File
@@ -595,6 +595,86 @@ 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;
}
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( 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 +686,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 +752,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. */
+1 -1
View File
@@ -82,7 +82,7 @@ proc get_struct_docs {data names} {
set current_doc ""
}
set subject n/a
regexp {^ *([[:alpha:]]*)} $line -> subject
regexp {^ *([[:alnum:]_]*)} $line -> subject
if {[lsearch $names $subject]>=0} {
set current_header $subject
} else {
+10 -9
View File
@@ -379,9 +379,9 @@ struct Fts5ExtensionApi {
/* Below this point are iVersion>=4 only */
int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
int (*xTokenize_v2)(Fts5Context*,
const char *pText, int nText, /* Text to tokenize */
const char *pLoc, int nLoc, /* Locale to pass to tokenizer */
void *pCtx, /* Context passed to xToken() */
const char *pText, int nText, /* Text to tokenize */
const char *pLocale, int nLocale, /* Locale to pass to tokenizer */
void *pCtx, /* Context passed to xToken() */
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
);
};
@@ -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
**
+51 -3
View File
@@ -746,6 +746,53 @@ static void fts5Bm25Function(
}
}
/*
** Implementation of fts5_get_locale() function.
*/
static void fts5GetLocaleFunction(
const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
Fts5Context *pFts, /* First arg to pass to pApi functions */
sqlite3_context *pCtx, /* Context for returning result/error */
int nVal, /* Number of values in apVal[] array */
sqlite3_value **apVal /* Array of trailing arguments */
){
int iCol = 0;
int eType = 0;
int rc = SQLITE_OK;
const char *zLocale = 0;
int nLocale = 0;
/* xColumnLocale() must be available */
assert( pApi->iVersion>=4 );
if( nVal!=1 ){
const char *z = "wrong number of arguments to function fts5_get_locale()";
sqlite3_result_error(pCtx, z, -1);
return;
}
eType = sqlite3_value_numeric_type(apVal[0]);
if( eType!=SQLITE_INTEGER ){
const char *z = "non-integer argument passed to function fts5_get_locale()";
sqlite3_result_error(pCtx, z, -1);
return;
}
iCol = sqlite3_value_int(apVal[0]);
if( iCol<0 || iCol>=pApi->xColumnCount(pFts) ){
sqlite3_result_error_code(pCtx, SQLITE_RANGE);
return;
}
rc = pApi->xColumnLocale(pFts, iCol, &zLocale, &nLocale);
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pCtx, rc);
return;
}
sqlite3_result_text(pCtx, zLocale, nLocale, SQLITE_TRANSIENT);
}
int sqlite3Fts5AuxInit(fts5_api *pApi){
struct Builtin {
const char *zFunc; /* Function name (nul-terminated) */
@@ -753,9 +800,10 @@ int sqlite3Fts5AuxInit(fts5_api *pApi){
fts5_extension_function xFunc;/* Callback function */
void (*xDestroy)(void*); /* Destructor function */
} aBuiltin [] = {
{ "snippet", 0, fts5SnippetFunction, 0 },
{ "highlight", 0, fts5HighlightFunction, 0 },
{ "bm25", 0, fts5Bm25Function, 0 },
{ "snippet", 0, fts5SnippetFunction, 0 },
{ "highlight", 0, fts5HighlightFunction, 0 },
{ "bm25", 0, fts5Bm25Function, 0 },
{ "fts5_get_locale", 0, fts5GetLocaleFunction, 0 },
};
int rc = SQLITE_OK; /* Return code */
int i; /* To iterate through builtin functions */
+14 -12
View File
@@ -3267,7 +3267,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 +3289,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 +3313,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 +3334,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,9 +3350,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 );
return pMod->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken);
assert( p->bV2Native==0 );
UNUSED_PARAM2(pLocale,nLocale);
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;
+103
View File
@@ -0,0 +1,103 @@
# 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 {vtable constructor failed: t1}}
do_catchsql_test 1.3 {
DROP TABLE t1
} {1 {vtable constructor failed: t1}}
do_test 1.4 {
sqlite3_db_config db DEFENSIVE 0
} {0}
do_test 1.5 {
sqlite3_fts5_drop_corrupt_table db main t1
} {}
do_test 1.6 {
sqlite3_db_config db DEFENSIVE -1
} {0}
do_execsql_test 1.7 {
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
+24
View File
@@ -231,6 +231,30 @@ do_faultsim_test 9.2 -faults oom* -prep {
faultsim_test_result {0 1}
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 10.0 {
CREATE VIRTUAL TABLE ft USING fts5(x, locale=1);
INSERT INTO ft VALUES(fts5_locale('hello', 'one two three i ii iii'));
INSERT INTO ft VALUES('four five six iv v vi');
INSERT INTO ft VALUES('eight nine ten viii ix x');
} {}
do_execsql_test 10.1 {
SELECT fts5_get_locale(ft, 0) FROM ft WHERE x MATCH 'one AND two AND three'
} {hello}
faultsim_save_and_close
do_faultsim_test 10 -faults oom* -prep {
faultsim_restore_and_reopen
} -body {
execsql {
SELECT fts5_get_locale(ft, 0) FROM ft WHERE x MATCH 'one AND two AND three'
}
} -test {
faultsim_test_result {0 hello}
}
finish_test
+91
View File
@@ -572,5 +572,96 @@ do_test 12.0 {
} msg] $msg
} {1 {error in fts5_api.xCreateTokenizer_v2()}}
#-------------------------------------------------------------------------
# Tests for auxiliary function fts5_get_locale().
#
reset_db
# Check that if the table does not support locale=1, fts5_get_locale()
# always returns NULL.
do_execsql_test 13.1.0 {
CREATE VIRTUAL TABLE nolocale USING fts5(a, b);
INSERT INTO nolocale VALUES('one two three', 'four five six');
INSERT INTO nolocale VALUES('three two one', 'seven eight nine');
}
do_execsql_test 13.1.1 {
SELECT fts5_get_locale(nolocale, 0) IS NULL FROM nolocale;
} {1 1}
do_execsql_test 13.1.2 {
SELECT fts5_get_locale(nolocale, 1) IS NULL FROM nolocale('one + two');
} {1}
do_execsql_test 13.1.3 {
SELECT fts5_get_locale(nolocale, 0) IS NULL FROM nolocale('one AND two');
} {1 1}
do_execsql_test 13.1.4 {
SELECT
fts5_get_locale(nolocale, 1) IS NULL
FROM nolocale('three AND two') ORDER BY rank
} {1 1}
do_catchsql_test 13.1.5 {
SELECT fts5_get_locale(nolocale, 2) IS NULL FROM nolocale('three AND two');
} {1 {column index out of range}}
do_catchsql_test 13.1.6 {
SELECT fts5_get_locale(nolocale, -1) IS NULL FROM nolocale('three AND two');
} {1 {column index out of range}}
do_catchsql_test 13.1.7 {
SELECT fts5_get_locale(nolocale) IS NULL FROM nolocale('three AND two');
} {1 {wrong number of arguments to function fts5_get_locale()}}
do_catchsql_test 13.1.8 {
SELECT fts5_get_locale(nolocale, 0, 0) IS NULL FROM nolocale('three AND two');
} {1 {wrong number of arguments to function fts5_get_locale()}}
do_catchsql_test 13.1.9 {
SELECT fts5_get_locale(nolocale, 'text') FROM nolocale('three AND two');
} {1 {non-integer argument passed to function fts5_get_locale()}}
# Check that if the table does support locale=1, fts5_get_locale()
# returns the locale of the identified row/column.
do_execsql_test 13.2.0 {
CREATE VIRTUAL TABLE ft USING fts5(a, b, locale=1);
INSERT INTO ft VALUES(
fts5_locale('th_TH', 'one two three'), 'four five six seven'
);
INSERT INTO ft VALUES(
'three two one', fts5_locale('en_AU', 'seven eight nine')
);
}
do_execsql_test 13.2.1 {
SELECT quote(fts5_get_locale(ft, 0)), quote(fts5_get_locale(ft, 1)) FROM ft
} { 'th_TH' NULL NULL 'en_AU' }
do_execsql_test 13.2.2 {
SELECT
quote(fts5_get_locale(ft, 0)), quote(fts5_get_locale(ft, 1))
FROM ft('one AND three')
} { 'th_TH' NULL NULL 'en_AU' }
do_execsql_test 13.2.3 {
SELECT
quote(fts5_get_locale(ft, 0)), quote(fts5_get_locale(ft, 1))
FROM ft('one AND three') ORDER BY rank
} { NULL 'en_AU' 'th_TH' NULL }
do_execsql_test 13.2.4 {
SELECT
quote(fts5_get_locale(ft, 0)), quote(fts5_get_locale(ft, 1))
FROM ft('one AND three') ORDER BY rowid
} { 'th_TH' NULL NULL 'en_AU' }
do_execsql_test 13.2.5 {
SELECT
quote(fts5_get_locale(ft, '0')), quote(fts5_get_locale(ft, 1))
FROM ft('one AND three') ORDER BY rowid
} { 'th_TH' NULL NULL 'en_AU' }
do_catchsql_test 13.2.6 {
SELECT
quote(fts5_get_locale(ft, '0.0')), quote(fts5_get_locale(ft, 1))
FROM ft('one AND three') ORDER BY rowid
} {1 {non-integer argument passed to function fts5_get_locale()}}
do_catchsql_test 13.2.7 {
SELECT
quote(fts5_get_locale(ft, 0.0)), quote(fts5_get_locale(ft, 1))
FROM ft('one AND three') ORDER BY rowid
} {1 {non-integer argument passed to function fts5_get_locale()}}
finish_test
+223 -31
View File
@@ -90,6 +90,26 @@
** and a very large cost if either start or stop are unavailable. This
** encourages the query planner to order joins such that the bounds of the
** series are well-defined.
**
** Update on 2024-08-22:
** xBestIndex now also looks for equality and inequality constraints against
** the value column and uses those constraints as additional bounds against
** the sequence range. Thus, a query like this:
**
** SELECT value FROM generate_series($SA,$EA)
** WHERE value BETWEEN $SB AND $EB;
**
** Is logically the same as:
**
** SELECT value FROM generate_series(max($SA,$SB),min($EA,$EB));
**
** Constraints on the value column can server as substitutes for constraints
** on the hidden start and stop columns. So, the following two queries
** are equivalent:
**
** SELECT value FROM generate_series($S,$E);
** SELECT value FROM generate_series WHERE value BETWEEN $S and $E;
**
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
@@ -131,8 +151,10 @@ static sqlite3_int64 genSeqMember(
typedef unsigned char u8;
typedef struct SequenceSpec {
sqlite3_int64 iBase; /* Starting value ("start") */
sqlite3_int64 iTerm; /* Given terminal value ("stop") */
sqlite3_int64 iOBase; /* Original starting value ("start") */
sqlite3_int64 iOTerm; /* Original terminal value ("stop") */
sqlite3_int64 iBase; /* Starting value to actually use */
sqlite3_int64 iTerm; /* Terminal value to actually use */
sqlite3_int64 iStep; /* Increment ("step") */
sqlite3_uint64 uSeqIndexMax; /* maximum sequence index (aka "n") */
sqlite3_uint64 uSeqIndexNow; /* Current index during generation */
@@ -325,9 +347,9 @@ static int seriesColumn(
series_cursor *pCur = (series_cursor*)cur;
sqlite3_int64 x = 0;
switch( i ){
case SERIES_COLUMN_START: x = pCur->ss.iBase; break;
case SERIES_COLUMN_STOP: x = pCur->ss.iTerm; break;
case SERIES_COLUMN_STEP: x = pCur->ss.iStep; break;
case SERIES_COLUMN_START: x = pCur->ss.iOBase; break;
case SERIES_COLUMN_STOP: x = pCur->ss.iOTerm; break;
case SERIES_COLUMN_STEP: x = pCur->ss.iStep; break;
default: x = pCur->ss.iValueNow; break;
}
sqlite3_result_int64(ctx, x);
@@ -335,7 +357,9 @@ static int seriesColumn(
}
#ifndef LARGEST_UINT64
#define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
#define LARGEST_UINT64 (0xffffffff|(((sqlite3_uint64)0xffffffff)<<32))
#define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif
/*
@@ -376,13 +400,18 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
** parameter. (idxStr is not used in this implementation.) idxNum
** is a bitmask showing which constraints are available:
**
** 0x01: start=VALUE
** 0x02: stop=VALUE
** 0x04: step=VALUE
** 0x08: descending order
** 0x10: ascending order
** 0x20: LIMIT VALUE
** 0x40: OFFSET VALUE
** 0x0001: start=VALUE
** 0x0002: stop=VALUE
** 0x0004: step=VALUE
** 0x0008: descending order
** 0x0010: ascending order
** 0x0020: LIMIT VALUE
** 0x0040: OFFSET VALUE
** 0x0080: value=VALUE
** 0x0100: value>=VALUE
** 0x0200: value>VALUE
** 0x1000: value<=VALUE
** 0x2000: value<VALUE
**
** This routine should initialize the cursor and position it so that it
** is pointing at the first row, or pointing off the end of the table
@@ -395,6 +424,12 @@ static int seriesFilter(
){
series_cursor *pCur = (series_cursor *)pVtabCursor;
int i = 0;
int returnNoRows = 0;
sqlite3_int64 iMin = SMALLEST_INT64;
sqlite3_int64 iMax = LARGEST_INT64;
sqlite3_int64 iLimit = 0;
sqlite3_int64 iOffset = 0;
(void)idxStrUnused;
if( idxNum & 0x01 ){
pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
@@ -416,16 +451,98 @@ static int seriesFilter(
}else{
pCur->ss.iStep = 1;
}
/* If there are constraints on the value column but there are
** no constraints on the start, stop, and step columns, then
** initialize the default range to be the entire range of 64-bit signed
** integers. This range will contracted by the value column constraints
** further below.
*/
if( (idxNum & 0x05)==0 && (idxNum & 0x0380)!=0 ){
pCur->ss.iBase = SMALLEST_INT64;
}
if( (idxNum & 0x06)==0 && (idxNum & 0x3080)!=0 ){
pCur->ss.iTerm = LARGEST_INT64;
}
pCur->ss.iOBase = pCur->ss.iBase;
pCur->ss.iOTerm = pCur->ss.iTerm;
/* Extract the LIMIT and OFFSET values, but do not apply them yet.
** The range must first be constrained by the limits on value.
*/
if( idxNum & 0x20 ){
sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]);
sqlite3_int64 iTerm;
iLimit = sqlite3_value_int64(argv[i++]);
if( idxNum & 0x40 ){
sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]);
if( iOffset>0 ){
pCur->ss.iBase += pCur->ss.iStep*iOffset;
iOffset = sqlite3_value_int64(argv[i++]);
}
}
if( idxNum & 0x3380 ){
/* Extract the maximum range of output values determined by
** constraints on the "value" column.
*/
if( idxNum & 0x0080 ){
iMin = iMax = sqlite3_value_int64(argv[i++]);
}else{
if( idxNum & 0x0300 ){
iMin = sqlite3_value_int64(argv[i++]);
if( idxNum & 0x0200 ){
if( iMin==LARGEST_INT64 ){
returnNoRows = 1;
}else{
iMin++;
}
}
}
if( idxNum & 0x3000 ){
iMax = sqlite3_value_int64(argv[i++]);
if( idxNum & 0x2000 ){
if( iMax==SMALLEST_INT64 ){
returnNoRows = 1;
}else{
iMax--;
}
}
}
if( iMin>iMax ){
returnNoRows = 1;
}
}
/* Try to reduce the range of values to be generated based on
** constraints on the "value" column.
*/
if( pCur->ss.iStep>0 ){
sqlite3_int64 szStep = pCur->ss.iStep;
if( pCur->ss.iBase<iMin ){
sqlite3_uint64 d = iMin - pCur->ss.iBase;
pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep;
}
if( pCur->ss.iTerm>iMax ){
sqlite3_uint64 d = pCur->ss.iTerm - iMax;
pCur->ss.iTerm -= ((d+szStep-1)/szStep)*szStep;
}
}else{
sqlite3_int64 szStep = -pCur->ss.iStep;
assert( szStep>0 );
if( pCur->ss.iBase>iMax ){
sqlite3_uint64 d = pCur->ss.iBase - iMax;
pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep;
}
if( pCur->ss.iTerm<iMin ){
sqlite3_uint64 d = iMin - pCur->ss.iTerm;
pCur->ss.iTerm += ((d+szStep-1)/szStep)*szStep;
}
}
}
/* Apply LIMIT and OFFSET constraints, if any */
if( idxNum & 0x20 ){
if( iOffset>0 ){
pCur->ss.iBase += pCur->ss.iStep*iOffset;
}
if( iLimit>=0 ){
sqlite3_int64 iTerm;
iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
if( pCur->ss.iStep<0 ){
if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
@@ -434,16 +551,21 @@ static int seriesFilter(
}
}
}
for(i=0; i<argc; i++){
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
/* If any of the constraints have a NULL value, then return no rows.
** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
pCur->ss.iBase = 1;
pCur->ss.iTerm = 0;
pCur->ss.iStep = 1;
returnNoRows = 1;
break;
}
}
if( returnNoRows ){
pCur->ss.iBase = 1;
pCur->ss.iTerm = 0;
pCur->ss.iStep = 1;
}
if( idxNum & 0x08 ){
pCur->ss.isReversing = pCur->ss.iStep > 0;
}else{
@@ -464,13 +586,35 @@ static int seriesFilter(
**
** The query plan is represented by bits in idxNum:
**
** 0x01 start = $value -- constraint exists
** 0x02 stop = $value -- constraint exists
** 0x04 step = $value -- constraint exists
** 0x08 output is in descending order
** 0x10 output is in ascending order
** 0x20 LIMIT $value -- constraint exists
** 0x40 OFFSET $value -- constraint exists
** 0x0001 start = $num
** 0x0002 stop = $num
** 0x0004 step = $num
** 0x0008 output is in descending order
** 0x0010 output is in ascending order
** 0x0020 LIMIT $num
** 0x0040 OFFSET $num
** 0x0080 value = $num
** 0x0100 value >= $num
** 0x0200 value > $num
** 0x1000 value <= $num
** 0x2000 value < $num
**
** Only one of 0x0100 or 0x0200 will be returned. Similarly, only
** one of 0x1000 or 0x2000 will be returned. If the 0x0080 is set, then
** none of the 0xff00 bits will be set.
**
** The order of parameters passed to xFilter is as follows:
**
** * The argument to start= if bit 0x0001 is in the idxNum mask
** * The argument to stop= if bit 0x0002 is in the idxNum mask
** * The argument to step= if bit 0x0004 is in the idxNum mask
** * The argument to LIMIT if bit 0x0020 is in the idxNum mask
** * The argument to OFFSET if bit 0x0040 is in the idxNum mask
** * The argument to value=, or value>= or value> if any of
** bits 0x0380 are in the idxNum mask
** * The argument to value<= or value< if either of bits 0x3000
** are in the mask
**
*/
static int seriesBestIndex(
sqlite3_vtab *pVTab,
@@ -483,7 +627,9 @@ static int seriesBestIndex(
#endif
int unusableMask = 0; /* Mask of unusable constraints */
int nArg = 0; /* Number of arguments that seriesFilter() expects */
int aIdx[5]; /* Constraints on start, stop, step, LIMIT, OFFSET */
int aIdx[7]; /* Constraints on start, stop, step, LIMIT, OFFSET,
** and value. aIdx[5] covers value=, value>=, and
** value>, aIdx[6] covers value<= and value< */
const struct sqlite3_index_constraint *pConstraint;
/* This implementation assumes that the start, stop, and step columns
@@ -491,7 +637,7 @@ static int seriesBestIndex(
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = -1;
aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = aIdx[5] = aIdx[6] = -1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
int iCol; /* 0 for start, 1 for stop, 2 for step */
@@ -512,7 +658,50 @@ static int seriesBestIndex(
}
continue;
}
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
if( pConstraint->iColumn==SERIES_COLUMN_VALUE ){
switch( op ){
case SQLITE_INDEX_CONSTRAINT_EQ:
case SQLITE_INDEX_CONSTRAINT_IS: {
idxNum |= 0x0080;
idxNum &= ~0x3300;
aIdx[5] = i;
aIdx[6] = -1;
bStartSeen = 1;
break;
}
case SQLITE_INDEX_CONSTRAINT_GE: {
if( idxNum & 0x0080 ) break;
idxNum |= 0x0100;
idxNum &= ~0x0200;
aIdx[5] = i;
bStartSeen = 1;
break;
}
case SQLITE_INDEX_CONSTRAINT_GT: {
if( idxNum & 0x0080 ) break;
idxNum |= 0x0200;
idxNum &= ~0x0100;
aIdx[5] = i;
bStartSeen = 1;
break;
}
case SQLITE_INDEX_CONSTRAINT_LE: {
if( idxNum & 0x0080 ) break;
idxNum |= 0x1000;
idxNum &= ~0x2000;
aIdx[6] = i;
break;
}
case SQLITE_INDEX_CONSTRAINT_LT: {
if( idxNum & 0x0080 ) break;
idxNum |= 0x2000;
idxNum &= ~0x1000;
aIdx[6] = i;
break;
}
}
continue;
}
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
assert( iCol>=0 && iCol<=2 );
iMask = 1 << iCol;
@@ -534,7 +723,7 @@ static int seriesBestIndex(
idxNum &= ~0x60;
aIdx[4] = 0;
}
for(i=0; i<5; i++){
for(i=0; i<7; i++){
if( (j = aIdx[i])>=0 ){
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
pIdxInfo->aConstraintUsage[j].omit =
@@ -582,6 +771,9 @@ static int seriesBestIndex(
pIdxInfo->estimatedRows = 2147483647;
}
pIdxInfo->idxNum = idxNum;
#ifdef SQLITE_INDEX_SCAN_HEX
pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_HEX;
#endif
return SQLITE_OK;
}
+33 -35
View File
@@ -1,9 +1,9 @@
C Add\sthe\snew\sSQLITE_TESTCTRL_OPTGET\sthat\sretrieves\sthe\scurrent\soptimization\nsetting.\s\sUse\sthis\sin\sthe\sCLI\sto\sprovide\ssymbolic\sfine-grain\scontrol\nover\soptimization\ssettings\susing\sthe\s".testctrl\sopt"\sdot-command.
D 2024-08-21T18:57:55.594
C Fix\stypo\sin\sthe\sprevious\scheck-in.\s\sEnsure\sthat\s--status\sheader\slines\sdo\snot\noverflow\sand\swrap.
D 2024-08-27T19:48:19.164
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 209e9c64edf499b0ea7a15448699101c01d15828af35a3439d32fc25fdf1b787
F Makefile.in 101cb90f75c16ca3f8e7088364322441f9b01d6fdcef4a9c7f5fdcf78a3601a4
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc 6c3fe8b6ce60e73f34a148c957d78b4648745c8d30e792423aa1a8d8bf12d065
F README.md 3d47ef5758e2de29d6f4e1aca714d51424baba86c8b561fef330f6ef2dc9282c
@@ -35,8 +35,8 @@ F autoconf/tea/win/nmakehlp.c b01f822eabbe1ed2b64e70882d97d48402b42d2689a1ea0034
F autoconf/tea/win/rules.vc 7b3bb2ef32ade0f3f14d951231811678722725e3bca240dd9727ae0dfe10f6a5
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
F configure 956e132a3e2481e5016e9ecaa0a2bdd9df95c1d923fa4fb2aa2cf9f0b3a54ad9 x
F configure.ac fd9ff064b142682964971fec3d867235e51e1f6de30a031e33f683b7699338ff
F configure 49523f0a070b583cea040d26eff53a65fb0893eca4663b1343a4d5a9a964da53 x
F configure.ac a100ebf7a07f5dedd319ef547dd467d1676ed059b85a7877aa9c44ac309f7000
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/compile-for-windows.md e8635eea9153dcd6a51fd2740666ebc4492b3813cb1ac31cd8e99150df91762d
@@ -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 6e02dea912a49f55785b0027fe77960aafee6c236307c23f82ec86a69f1a2001 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
@@ -91,18 +91,18 @@ F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
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 1db7f85f4d84b7b6f33336155d5053fafc3c8debd074422d8003c8f7fa4d0fdb
F ext/fts5/fts5.h c65fc7799a4cd6774628da4fa9408955623e504d7369ab5b89c4413fdfe11eb5
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
F ext/fts5/fts5.h efaaac0df3d3bc740383044c144b582f47921aafa21d7b10eb98f42c24c740b0
F ext/fts5/fts5Int.h 26a71a09cefa4ef6b4516b204ed48da3e1380970a19b3482eea7c5d805655360
F ext/fts5/fts5_aux.c 12cd2512f869217c38b70c31de5b5f741812734fafa80f55b32ea9bbd96e2152
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 5ea7ab0c9967594e73b7dd0ad737595922a14f175aa4b486dc2992a3e3138b68
F ext/fts5/fts5_main.c 0dbe241c50b62e24a229a176d66d580e359b3c32cb0970c39bb6dd6b86e125d5
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
@@ -153,6 +153,7 @@ F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93
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 f78b6de9e4327e16ba7a7958b1ce576f9b5d886b4b97690f90b7f3cf654da458
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
@@ -177,7 +178,7 @@ 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 fbc65a64944fb747f6d3fb30628a807d5cce1bca43c11df40e7770ad7a7ed593
F ext/fts5/test/fts5faultI.test e1e8a927122a8c3be8614a59717e838cad0505ba0a6f404983da8430e7aeb14d
F ext/fts5/test/fts5first.test bfd685b96905bf541d99d8644e0a7219d1d833455a08ab64e344071a613b6ba9
F ext/fts5/test/fts5full.test 97d263c1072f4a560929cca31e70f65d2ae232610e17e6affcf7e979df59547b
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
@@ -187,7 +188,7 @@ F ext/fts5/test/fts5interrupt.test 20d04204d3e341b104c0c24a41596b6393a3a81eba104
F ext/fts5/test/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400f8d2d27ea9373e0c4a1
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fce79fa43004dff01c
F ext/fts5/test/fts5locale.test 79cbd3000ae269de50826f6061c81f7c9fdb21dd9954c0b7f9485263482c539d
F ext/fts5/test/fts5locale.test 797cf6f5e017462ab11313ce884b9f1df8ff063811e74ef42190cd19ed6b600b
F ext/fts5/test/fts5matchinfo.test 877520582feb86bbfd95ab780099bcba4526f18ac75ee34979144cf86ba3a5a3
F ext/fts5/test/fts5merge.test 2654df0bcdb2d117c2d38b6aeb0168061be01c643f9e9194b36c43a2970e8082
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
@@ -417,7 +418,7 @@ F ext/misc/regexp.c 4bdd0045912f81c84908bd535ec5ad3b1c8540b4287c70ab840709636240
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
F ext/misc/series.c d96e5aac21658c6b5d54f918ac140460ec7197734c1a4fba806950831a7b1e7a
F ext/misc/series.c a6089b5e8e3002bd1e5d9877cee6aead0b9a6426e406c09a399817db9e9ae823
F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d
F ext/misc/shathree.c 1821d90a0040c9accdbe3e3527d378d30569475d758aa70f6848924c0b430e8c
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
@@ -712,7 +713,7 @@ F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 64e4b1227b4ed123146f0aa2989131d1fbd9b927b11e80c9d58c6a68f9cd5ce3
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 444c4d1eaac40103461e3b6f0881846dd3aafc1cec1dd169d3482fa331667da7
F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
@@ -762,11 +763,11 @@ F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c d99931f45416652895e502328ca49fe782cfc4e1ebdcda13b3736d991ebf42ce
F src/printf.c 6a87534ebfb9e5346011191b1f3a7ebc457f5938c7e4feeea478ecf53f6a41b2
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 9afed5fd7b9111633bdb74a73cdc47324e28e4dc6c27113e3e9aee38fb9422ab
F src/resolve.c 2c127880c0634962837f16f2f48a295e514357af959330cc038de73015d5b5e8
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4b14337a2742f0c0beeba490e9a05507e9b4b12184b9cd12773501d08d48e3fe
F src/shell.c.in 9a45cd618ed3cd09927e04bb0ccfd929fb5efa03a7166daec4645d230b7267f3
F src/sqlite.h.in c6512f60f9fe06de46e49161e3f8fca72f3875f67dad8eaf469622567f434e48
F src/shell.c.in 40de636c1d90fb8a9ca7f49dc8f50d930f1b60736e73aca5eb37c4c7d0e47f9d
F src/sqlite.h.in f07bff4225a1244efd604a0ffef81ed69f29d3dbaed7e22f906f26229ba3ca9e
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
F src/sqliteInt.h 28c878bdf528879afefe1994ac007d094f8061f2fdacdc55d6055d7e9341151e
@@ -834,7 +835,7 @@ 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
@@ -850,9 +851,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c 61fea6c34c9c2350b114a4f64dce51ec073c2d8c50ca0734a0882ba6ab531805
F src/whereInt.h 6444b888ce395cb80511284b8a73b63472d34247fcb1b125ee06a54fa6ae878e
F src/wherecode.c 137797b0de9ddf1ff43e5b0edffcc76fb05184ed651fc4f5a0a01a45c0b89d04
F src/where.c c046dd58c3410f7b7528e1e6317cb876398557bad346d568ed8562321a7d002d
F src/whereInt.h a5d079c346a658b7a6e9e47bb943d021e02fa1e6aed3b964ca112112a4892192
F src/wherecode.c 5172d647798134e7c92536ddffe7e530c393d79b5dedd648b88faf2646c65baf
F src/whereexpr.c 44f41ae554c7572e1de1485b3169b233ee04d464b2ee5881687ede3bf07cacfa
F src/window.c 499d48f315a09242dc68f2fac635ed27dcf6bbb0d9ab9084857898c64489e975
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1441,7 +1442,7 @@ F test/memjournal2.test dbc2c5cb5f7b38950f4f6dc3e73fcecf0fcbed3fc32c7ce913bba164
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 86b8158752af9188ed5b32a30674a1ef71183e6bc4e6808e815cd658ca9058a6
F test/memsubsys2.test 774b93cb09ca50d1b759bb7c645baa2a9ce172edc3a3da67d5150a26a9fc2a08
F test/merge1.test 2de6d6ef8d25402764b1aab49d8f9d7f89208c89a6674e437f76de4c812157b8
F test/merge1.test 7dd9dc6838bcd0623a069485fe3a8dd498a051c16e1877cf84f506c0d6a29b43
F test/minmax.test fe638b55d77d2375531a8f549b338eafcd9adfbd2f72df37ed77d9b26ca0a71a
F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
@@ -1700,7 +1701,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a067468b43b8cb2305e9f9fe414e5f40c875bb5d2cba5f00b8154396e95fcf37
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test f150d206294471d20f50029e6b46b76b87a7a010b16dc57eb44245c76dd02802
F test/tabfunc01.test 6002a5f37b76355f173c75c2b3b03173b19d6a8b078c5baaa4c78bbcd0fa6323
F test/table.test 7862a00b58b5541511a26757ea9c5c7c3f8298766e98aa099deec703d9c0a8e0
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1712,9 +1713,9 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl e88c498c369cff6bf0898db6d04088685066730be51821ef775ef13fd2b1d077
F test/testrunner.tcl 5d02deeba7a53baeadae6aa7641d90aac58fdfa3a7bcac85cfcfd752b1aab87c
F test/testrunner_data.tcl c5ae2b1f9a99210b0600d002fb3af1fee350997cee9416551e83b93501360ebf
F test/tester.tcl 2c203a2dd664298f239f0ec3ce22fbc65b5f021c1e09edbae8452af8a694e052
F test/testrunner.tcl c27905c57f54450411be922037d227fee65b08928d09715d784380a398b0e758
F test/testrunner_data.tcl 6a0facfbff26f2f8573ebaeb209426bbb59809d5c0f6925f983bd030ab5248cd
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -2069,7 +2070,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 6ba0c8048e4cc02b942e56640f8fcd50fd7ca72c876656c40f6baf42e316684c
F test/windowE.test c98507e0b0d95980ad25845db758557757be2d7054198ccf522c7d277057a3df
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
@@ -2210,11 +2211,8 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 6b024c85ef856e26cddac8ad862e16909b5149c3e3efb4e73ba54c97291f1cc4
R 5688f40bf117ffce0b629c4446a727b9
T *branch * optimization-onoff
T *sym-optimization-onoff *
T -sym-trunk *
P 7c195f132cb48ee44124eb4af3532937493429f7c45f6ac611f7a9b128799ad7
R 15868716c90b102057036239341d8066
U drh
Z b26803088924fd26f08434065f39c8bf
Z fde036223228b7af985cf94952c295a1
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
0ea4e1e8fc689cb1af3a8d21dd6af9d483115412b414e85e8a42480f50d65af2
2eaea67495fd9961b7145d829789889bf1d8fa7a834d40d1be43e7c74c233bc2
+1
View File
@@ -279,6 +279,7 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
pIdxInfo->orderByConsumed = 1;
pIdxInfo->idxNum |= 0x08;
}
pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_HEX;
return SQLITE_OK;
}
+2 -2
View File
@@ -1300,9 +1300,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3WalkExprList(pWalker, pExpr->pLeft->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pWin ){
if( pWin && pParse->nErr==0 ){
Select *pSel = pNC->pWinSelect;
assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) );
assert( ExprUseYWin(pExpr) && pWin==pExpr->y.pWin );
if( IN_RENAME_OBJECT==0 ){
sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
if( pParse->db->mallocFailed ) break;
+22 -10
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,11 +280,12 @@ 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. */
/* These next 3 macros are for emitting formatted output. When complaints
* from the WASM build are issued for non-formatted output, (when a mere
* from the WASM build are issued for non-formatted output, when a mere
* string literal is to be emitted, the ?putz(z) forms should be used.
* (This permits compile-time checking of format string / argument mismatch.)
*/
@@ -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 */
@@ -534,6 +537,14 @@ static char *shell_strncpy(char *dest, const char *src, size_t n){
return dest;
}
/*
** strcpy() workalike to squelch an unwarranted link-time warning
** from OpenBSD.
*/
static void shell_strcpy(char *dest, const char *src){
while( (*(dest++) = *(src++))!=0 ){}
}
/*
** Optionally disable dynamic continuation prompt.
** Unless disabled, the continuation prompt shows open SQL lexemes if any,
@@ -599,7 +610,7 @@ static char *dynamicContinuePrompt(void){
size_t ncp = strlen(continuePrompt);
size_t ndp = strlen(dynPrompt.zScannerAwaits);
if( ndp > ncp-3 ) return continuePrompt;
strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits);
shell_strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits);
while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' ';
shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
PROMPT_LEN_MAX-4);
@@ -3548,10 +3559,11 @@ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
}else if( strncmp(zVar, "$int_", 5)==0 ){
sqlite3_bind_int(pStmt, i, atoi(&zVar[5]));
}else if( strncmp(zVar, "$text_", 6)==0 ){
char *zBuf = sqlite3_malloc64( strlen(zVar)-5 );
size_t szVar = strlen(zVar);
char *zBuf = sqlite3_malloc64( szVar-5 );
if( zBuf ){
memcpy(zBuf, &zVar[6], strlen(zVar)-5);
sqlite3_bind_text64(pStmt, i, zBuf, -1, sqlite3_free, SQLITE_UTF8);
memcpy(zBuf, &zVar[6], szVar-5);
sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
}
}else{
sqlite3_bind_null(pStmt, i);
@@ -11044,7 +11056,7 @@ static int do_meta_command(char *zLine, ShellState *p){
for(ii=2; ii<nArg; ii++){
const char *z = azArg[ii];
int useLabel = 0;
const char *zLabel;
const char *zLabel = 0;
if( (z[0]=='+'|| z[0]=='-') && !IsDigit(z[1]) ){
useLabel = z[0];
zLabel = &z[1];
@@ -11061,11 +11073,11 @@ static int do_meta_command(char *zLine, ShellState *p){
}
if( jj>=ArraySize(aLabel) ){
eputf("Error: no such optimization: \"%s\"\n", zLabel);
eputf("Should be one of:");
eputz("Should be one of:");
for(jj=0; jj<ArraySize(aLabel); jj++){
eputf(" %s", aLabel[jj].zLabel);
}
eputf("\n");
eputz("\n");
rc = 1;
goto meta_command_exit;
}
@@ -11082,9 +11094,9 @@ static int do_meta_command(char *zLine, ShellState *p){
curOpt = ~newOpt;
}
if( newOpt==0 ){
oputf("+All\n");
oputz("+All\n");
}else if( newOpt==0xffffffff ){
oputf("-All\n");
oputz("-All\n");
}else{
int jj;
for(jj=0; jj<ArraySize(aLabel); jj++){
+8 -4
View File
@@ -7427,9 +7427,11 @@ struct sqlite3_module {
** will be returned by the strategy.
**
** The xBestIndex method may optionally populate the idxFlags field with a
** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
** assumes that the strategy may visit at most one row.
** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
** output to show the idxNum has hex instead of as decimal. Another flag is
** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
** return at most one row.
**
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
** SQLite also assumes that if a call to the xUpdate() method is made as
@@ -7493,7 +7495,9 @@ struct sqlite3_index_info {
** [sqlite3_index_info].idxFlags field to some combination of
** these bits.
*/
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */
#define SQLITE_INDEX_SCAN_HEX 0x00000002 /* Display idxNum as hex */
/* in EXPLAIN QUERY PLAN */
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
+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;
+2
View File
@@ -3987,6 +3987,7 @@ static int whereLoopAddBtree(
pNew->prereq = mPrereq;
pNew->nOut = rSize;
pNew->u.btree.pIndex = pProbe;
pNew->u.btree.pOrderBy = 0;
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
/* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
@@ -4349,6 +4350,7 @@ static int whereLoopAddVirtualOne(
pNew->u.vtab.idxStr = pIdxInfo->idxStr;
pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
pIdxInfo->nOrderBy : 0);
pNew->u.vtab.bIdxNumHex = (pIdxInfo->idxFlags&SQLITE_INDEX_SCAN_HEX)!=0;
pNew->rSetup = 0;
pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
+1
View File
@@ -149,6 +149,7 @@ struct WhereLoop {
int idxNum; /* Index number */
u32 needFree : 1; /* True if sqlite3_free(idxStr) is needed */
u32 bOmitOffset : 1; /* True to let virtual table handle offset */
u32 bIdxNumHex : 1; /* Show idxNum as hex in EXPLAIN QUERY PLAN */
i8 isOrdered; /* True if satisfies ORDER BY */
u16 omitMask; /* Terms that may be omitted */
char *idxStr; /* Index identifier string */
+3 -1
View File
@@ -200,7 +200,9 @@ int sqlite3WhereExplainOneScan(
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
sqlite3_str_appendall(&str, " VIRTUAL TABLE INDEX ");
sqlite3_str_appendf(&str,
pLoop->u.vtab.bIdxNumHex ? "0x%x:%s" : "%d:%s",
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
+12 -12
View File
@@ -64,21 +64,21 @@ do_eqp_test 101 {
| |--LEFT
| | `--MERGE (UNION ALL)
| | |--LEFT
| | | `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| | | `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
| | `--RIGHT
| | `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| | `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
| `--RIGHT
| `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
`--RIGHT
`--MERGE (UNION ALL)
|--LEFT
| `--MERGE (UNION ALL)
| |--LEFT
| | `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| | `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
| `--RIGHT
| `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
`--RIGHT
`--SCAN generate_series VIRTUAL TABLE INDEX 23:
`--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
}
# Same test with the blanced-merge optimization
@@ -129,17 +129,17 @@ do_eqp_test 111 {
| | | |--LEFT
| | | | `--MERGE (UNION ALL)
| | | | |--LEFT
| | | | | `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| | | | | `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
| | | | `--RIGHT
| | | | `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| | | | `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
| | | `--RIGHT
| | | `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| | | `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
| | `--RIGHT
| | `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| | `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
| `--RIGHT
| `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
`--RIGHT
`--SCAN generate_series VIRTUAL TABLE INDEX 23:
`--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
}
finish_test
+6 -6
View File
@@ -121,26 +121,26 @@ do_eqp_test tabfunc01-3.10 {
SELECT value FROM generate_series(1,10) ORDER BY value;
} {
QUERY PLAN
`--SCAN generate_series VIRTUAL TABLE INDEX 19:
`--SCAN generate_series VIRTUAL TABLE INDEX 0x13:
}
do_eqp_test tabfunc01-3.11 {
SELECT value FROM generate_series(1,10) ORDER BY +value;
} {
QUERY PLAN
|--SCAN generate_series VIRTUAL TABLE INDEX 3:
|--SCAN generate_series VIRTUAL TABLE INDEX 0x3:
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test tabfunc01-3.12 {
SELECT value FROM generate_series(1,10) ORDER BY value, stop;
} {
QUERY PLAN
`--SCAN generate_series VIRTUAL TABLE INDEX 19:
`--SCAN generate_series VIRTUAL TABLE INDEX 0x13:
}
do_eqp_test tabfunc01-3.13 {
SELECT value FROM generate_series(1,10) ORDER BY stop, value;
} {
QUERY PLAN
|--SCAN generate_series VIRTUAL TABLE INDEX 3:
|--SCAN generate_series VIRTUAL TABLE INDEX 0x3:
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -156,9 +156,9 @@ do_eqp_test tabfunc01-3.20 {
QUERY PLAN
`--MERGE (UNION ALL)
|--LEFT
| `--SCAN generate_series VIRTUAL TABLE INDEX 23:
| `--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
`--RIGHT
`--SCAN generate_series VIRTUAL TABLE INDEX 23:
`--SCAN generate_series VIRTUAL TABLE INDEX 0x17:
}
+1 -1
View File
@@ -985,7 +985,7 @@ proc query_plan_graph {sql} {
}
set a "\n QUERY PLAN\n"
append a [append_graph " " dx cx 0]
regsub -all { 0x[A-F0-9]+\y} $a { xxxxxx} a
regsub -all {SUBQUERY 0x[A-F0-9]+\y} $a {SUBQUERY xxxxxx} a
regsub -all {(MATERIALIZE|CO-ROUTINE|SUBQUERY) \d+\y} $a {\1 xxxxxx} a
regsub -all {\((join|subquery)-\d+\)} $a {(\1-xxxxxx)} a
return $a
+78 -31
View File
@@ -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
@@ -277,10 +279,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(
@@ -389,14 +393,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 +457,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"}
@@ -443,14 +474,10 @@ proc show_status {db cls} {
} 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\]$clreol"]
puts [format %-79.79s "Cores: $nJob max $S(running) active"]
puts [format %-79.79s "Summary: [elapsetime $tm], $fin/$total tasks,\
$ne errors, $nt tests"]
set srcdir [file dirname [file dirname $TRG(info_script)]]
if {$S(running)>0} {
@@ -470,7 +497,7 @@ proc show_status {db cls} {
}
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$clreol"]
}
}
if {$cls} {
@@ -842,6 +869,17 @@ proc add_tcl_jobs {build config patternlist {shelldepid ""}} {
if {[llength $patternlist]>0} {
set bMatch 0
foreach p $patternlist {
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 [file tail $f]]} {
set bMatch 1
break
@@ -1062,25 +1100,13 @@ proc add_jobs_from_cmdline {patternlist} {
}
release {
set patternlist [lrange $patternlist 1 end]
set config_set {}
foreach b [trd_builds $TRG(platform)] {
if {$TRG(config)!="" && ![regexp "\\y$b\\y" $TRG(config)]} continue
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
}
if {$patternlist==""} {
foreach e [trd_extras $TRG(platform) $b] {
if {$e=="fuzztest"} {
add_fuzztest_jobs $b
} else {
add_make_job $bld $e
}
}
}
lappend config_set $b
}
add_devtest_jobs $config_set [lrange $patternlist 1 end]
}
list {
@@ -1120,15 +1146,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 +1407,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.
+2 -6
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
@@ -116,6 +115,7 @@ namespace eval trd {
}
set build(Stdcall) {
-DUSE_STDCALL=1
-DSQLITE_USE_ONLY_WIN32=1
-O2
}
@@ -139,10 +139,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
@@ -222,7 +218,7 @@ namespace eval trd {
-DSQLITE_MAX_PAGE_SIZE=4096
-DSQLITE_OMIT_LOAD_EXTENSION=1
-DSQLITE_OMIT_PROGRESS_CALLBACK=1
-DSQLITE_OMIT_VIRTUALTABLE=1
-DSQLITE_OMIT_VIRTUALTABLEx=1
-DSQLITE_ENABLE_HIDDEN_COLUMNS
-DSQLITE_TEMP_STORE=3
}
+20
View File
@@ -54,5 +54,25 @@ do_execsql_test 1.3 {
5 5,4 5,4,1 5,4,1,6 5,4,1,6,3 5,4,1,6,3,2
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE TABLE t1(x);
}
sqlite3_create_aggregate db
breakpoint
do_catchsql_test 2.1 {
SELECT min(x) OVER w1 FROM t1
WINDOW w1 AS (PARTITION BY x_count(x) OVER w1);
} {1 {x_count() may not be used as a window function}}
do_catchsql_test 2.2 {
SELECT min(x) FILTER (WHERE x_count(x) OVER w1) OVER w1 FROM t1
WINDOW w1 AS (PARTITION BY x OVER w1);
} {1 {near "OVER": syntax error}}
finish_test