Merge trunk into this branch.

FossilOrigin-Name: 9c3bb3dc4f5b5cd7db6cd50d22dbe8f933cccf5f2fd253467bb50f36b3207a93
This commit is contained in:
stephan
2024-10-16 13:02:07 +00:00
38 changed files with 985 additions and 353 deletions
+61 -11
View File
@@ -66,6 +66,14 @@ USE_STDCALL = 0
USE_SEH = 1
!ENDIF
# Use STATICALLY_LINK_TCL=1 to statically link against TCL
#
!IFNDEF STATICALLY_LINK_TCL
STATICALLY_LINK_TCL = 0
!ELSEIF $(STATICALLY_LINK_TCL)!=0
CCOPTS = $(CCOPTS) -DSTATIC_BUILD
!ENDIF
# Set this non-0 to have the shell executable link against the core dynamic
# link library.
#
@@ -929,10 +937,9 @@ TCC = $(TCC) /fsanitize=address
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
!IFNDEF TCLVERSION
TCLVERSION = 86
!IF $(STATICALLY_LINK_TCL)!=0
TCLSUFFIX = s
!ENDIF
!IFNDEF TCLSUFFIX
TCLSUFFIX =
!ENDIF
@@ -941,6 +948,19 @@ TCLSUFFIX =
TCLDIR = C:\Tcl
!ENDIF
!IFNDEF TCLVERSION
!IF EXISTS("$(TCLDIR)\lib\tcl90$(TCLSUFFIX).lib")
TCLVERSION = 90
!ELSEIF EXISTS("$(TCLDIR)\lib\tcl86$(TCLSUFFIX).lib")
TCLVERSION = 86
!ELSEIF EXISTS("$(TCLDIR)\lib\tcl86t.lib")
TCLSUFFIX = t
TCLVERSION = 86
!ELSE
TCLVERSION = 90
!ENDIF
!ENDIF
!IFNDEF TCLINCDIR
TCLINCDIR = $(TCLDIR)\include
!ENDIF
@@ -953,9 +973,21 @@ TCLLIBDIR = $(TCLDIR)\lib
LIBTCL = tcl$(TCLVERSION)$(TCLSUFFIX).lib
!ENDIF
!IFNDEF TCLLIBS
!IF $(STATICALLY_LINK_TCL)!=0
TCLLIBS = /NODEFAULTLIB:libucrt.lib netapi32.lib user32.lib ucrt.lib
!ELSE
TCLLIBS =
!ENDIF
!ENDIF
!IFNDEF LIBTCLSTUB
!IF EXISTS("$(TCLLIBDIR)\tclstub$(TCLSUFFIX).lib")
LIBTCLSTUB = tclstub$(TCLSUFFIX).lib
!ELSE
LIBTCLSTUB = tclstub$(TCLVERSION)$(TCLSUFFIX).lib
!ENDIF
!ENDIF
!IFNDEF LIBTCLPATH
LIBTCLPATH = $(TCLDIR)\bin
@@ -1013,10 +1045,18 @@ LIBICU = icuuc.lib icuin.lib
# specific Tcl shell to use.
#
!IFNDEF TCLSH_CMD
!IF $(USE_TCLSH_IN_PATH)!=0 || !EXIST("$(TCLDIR)\bin\tclsh.exe")
TCLSH_CMD = tclsh
!ELSE
!IF EXISTS("$(TCLDIR)\bin\tclsh$(TCLVERSION).exe")
TCLSH_CMD = $(TCLDIR)\bin\tclsh$(TCLVERSION).exe
!ELSEIF EXISTS("$(TCLDIR)\bin\tclsh90.exe")
TCLSH_CMD = $(TCLDIR)\bin\tclsh90.exe
!ELSEIF EXISTS("$(TCLDIR)\bin\tclsh86.exe")
TCLSH_CMD = $(TCLDIR)\bin\tclsh86.exe
!ELSEIF EXISTS("$(TCLDIR)\bin\tclsh86t.exe")
TCLSH_CMD = $(TCLDIR)\bin\tclsh86t.exe
!ELSEIF EXISTS("$(TCLDIR)\bin\tclsh.exe")
TCLSH_CMD = $(TCLDIR)\bin\tclsh.exe
!ELSE
TCLSH_CMD = tclsh
!ENDIF
!ENDIF
# <</mark>>
@@ -1824,7 +1864,7 @@ tclsqlite3.def: tclsqlite.lo
pkgIndex.tcl: $(TOP)\VERSION
for /F %%V in ('type "$(TOP)\VERSION"') do ( \
echo package ifneeded sqlite3 @version@ [list load [file join $$dir $(SQLITE3TCLDLL)] sqlite3] \
echo package ifneeded sqlite3 @version@ [list load [file join $$dir $(SQLITE3TCLDLL)] Sqlite3] \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact @version@ %%V > pkgIndex.tcl \
)
@@ -1868,7 +1908,7 @@ dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbhash.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
RSYNC_SRC = \
$(TOP)\tool\sqlite3-rsync.c \
$(TOP)\tool\sqlite3_rsync.c \
$(SQLITE3C)
RSYNC_OPT = \
@@ -1877,7 +1917,7 @@ RSYNC_OPT = \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED
sqlite3-rsync.exe: $(RSYNC_SRC) $(LIBRESOBJS)
sqlite3_rsync.exe: $(RSYNC_SRC) $(LIBRESOBJS)
$(LTLINK) $(RSYNC_OPT) $(NO_WARN) $(RSYNC_SRC) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
scrub.exe: $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
@@ -2537,7 +2577,7 @@ extensiontest: testfixture.exe testloadext.dll
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe $(TOP)\tool\mktoolzip.tcl
tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe sqlite3_rsync.exe $(TOP)\tool\mktoolzip.tcl
.\testfixture.exe $(TOP)\tool\mktoolzip.tcl
coretestprogs: testfixture.exe sqlite3.exe
@@ -2746,6 +2786,16 @@ THREADTEST3_SRC = \
threadtest3.exe: $(THREADTEST3_SRC) $(TOP)\src\test_multiplex.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\test\threadtest3.c $(TOP)\src\test_multiplex.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
# Display key variables that control which version of TCL is to be used.
#
tcl-env:
@echo TCLDIR = $(TCLDIR)
@echo TCLVERSION = $(TCLVERSION)
@echo TCLSUFFIX = $(TCLSUFFIX)
@echo LIBTCL = $(LIBTCL)
@echo LIBTCLSTUB = $(LIBTCLSTUB)
@echo TCLSH_CMD = $(TCLSH_CMD)
LSMDIR=$(TOP)\ext\lsm1
!INCLUDE $(LSMDIR)\Makefile.msc
@@ -2779,7 +2829,7 @@ clean:
del /Q sqlite3.c sqlite3-*.c sqlite3.h 2>NUL
del /Q sqlite3rc.h 2>NUL
del /Q shell.c sqlite3ext.h sqlite3session.h 2>NUL
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c sqlite3-rsync.exe 2>NUL
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c sqlite3_rsync.exe 2>NUL
del /Q sqlite-*-output.vsix 2>NUL
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL
del /Q sqltclsh.* 2>NUL
+8
View File
@@ -66,6 +66,14 @@ USE_STDCALL = 0
USE_SEH = 1
!ENDIF
# Use STATICALLY_LINK_TCL=1 to statically link against TCL
#
!IFNDEF STATICALLY_LINK_TCL
STATICALLY_LINK_TCL = 0
!ELSEIF $(STATICALLY_LINK_TCL)!=0
CCOPTS = $(CCOPTS) -DSTATIC_BUILD
!ENDIF
# Set this non-0 to have the shell executable link against the core dynamic
# link library.
#
@@ -3,6 +3,27 @@ Architecture (TEA). For additional information on SQLite see
http://www.sqlite.org/
-------------------------------------------------------------------
Update 2024-10-11:
A better way to build the TCL extension for SQLite is to use the
canonical source code tarball. For Unix:
./configure --with-tclsh=$(TCLSH)
make tclextension-install
For Windows:
nmake /f Makefile.msc tclextension-install TCLSH_CMD=$(TCLSH)
In both of the above, replace $(TCLSH) with the full pathname of
of the tclsh that you want the SQLite extension to work with.
This TEA builder is antiquated. It does not work for TCL9. The
SQLite devs don't know how to fix it. If you would like to help
fix it, contact us.
------------------------------------------------------------------
UNIX BUILD
==========
+2 -2
View File
@@ -3,8 +3,8 @@
#
if {[package vsatisfies [package provide Tcl] 9.0-]} {
package ifneeded sqlite3 @PACKAGE_VERSION@ \
[list load [file join $dir @PKG_LIB_FILE9@] sqlite3]
[list load [file join $dir @PKG_LIB_FILE9@] Sqlite3]
} else {
package ifneeded sqlite3 @PACKAGE_VERSION@ \
[list load [file join $dir @PKG_LIB_FILE8@] sqlite3]
[list load [file join $dir @PKG_LIB_FILE8@] Sqlite3]
}
+1 -1
View File
@@ -407,7 +407,7 @@ install-libraries:
@echo Installing package index in '$(SCRIPT_INSTALL_DIR)'
@type << >"$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
package ifneeded $(PROJECT) $(DOTVERSION) \
[list load [file join $$dir $(PRJLIBNAME)] sqlite3]
[list load [file join $$dir $(PRJLIBNAME)] Sqlite3]
<<
install-docs:
+1 -1
View File
@@ -128,7 +128,7 @@ AC_ARG_ENABLE(tcl,
[use_tcl=$enableval],[use_tcl=yes])
original_use_tcl=${use_tcl}
if test x"${with_tclsh}" == x -a x"${with_tcl}" == x; then
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.6 tclsh tclsh9.0],none)
AC_CHECK_PROGS(TCLSH_CMD, [tclsh9.0 tclsh8.6 tclsh],none)
with_tclsh=${TCLSH_CMD}
fi
if test x"${with_tclsh}" != x -a x"${with_tclsh}" != xnone; then
+58
View File
@@ -0,0 +1,58 @@
# Notes On Compiling SQLite On All Kinds Of Unix
Here are step-by-step instructions on how to build SQLite from
canonical source on any modern machine that isn't Windows. These
notes are tested (on 2024-10-11) on Ubuntu and on MacOS, but they
are general and should work on most any modern unix platform.
1. Install a C-compiler. GCC or Clang both work fine. If you are
reading this document, you've probably already done that.
2. Install TCL9 development libraries. In this note, we'll do a
private install in the $HOME/local directory, but you can make
adjustments to install TCL9 wherever you like.
install the TCL development libraries in the "`c:\Tcl`" directory.
<p>
This document assumes you are working with <b>TCL version 9.0</b>.
<ol type="a">
<li>Get the TCL source archive, perhaps from
[https://www.tcl.tk/software/tcltk/download.html](https://www.tcl.tk/software/tcltk/download.html)
or [https://sqlite.org/tmp/tcl9.0.0.tar.gz](https://sqlite.org/tmp/tcl9.0.0.tar.gz)
<li>Untar the source archive. CD into the "unix/" subfolder
of the source tree.
<li>Run: `mkdir $HOME/local`
<li>Run: `./configure --prefix=$HOME/local`
<li>Run: `make install`
</ol>
4. Download the SQLite source tree and unpack it. CD into the
toplevel directory of the source tree.
5. Run: `./configure --enable-all --with-tclsh=$HOME/local/bin/tclsh9.0`
You do not need to use --with-tclsh if the tclsh you want to use is the
first one on your PATH.
6. Run the "`Makefile`" makefile with an appropriate target.
Examples:
<ul>
<li> `make sqlite3.c`
<li> `make sqlite3`
<li> `make sqldiff`
<li> `make sqlite3_rsync`
<li> `make tclextension-install`
<li> `make devtest`
<li> `make releasetest`
<li> `make sqlite3_analyzer`
</ul>
It is not required that you run the "tclextension-install" target prior to
running tests. However, the tests will run more smoothly if you do.
The version of SQLite used for the TCL extension does *not* need to
correspond to the version of SQLite under test. So you can install the
SQLite TCL extension once, and then use it to test many different versions
of SQLite.
7. For a debugging build of the CLI, where the ".treetrace" and ".wheretrace"
commands work, add the the --enable-debug argument to configure.
+18 -19
View File
@@ -1,7 +1,7 @@
# Notes On Compiling SQLite On Windows 11
Here are step-by-step instructions on how to build SQLite from
canonical source on a new Windows 11 PC, as of 2023-11-01:
canonical source on a new Windows 11 PC, as of 2024-10-09:
1. Install Microsoft Visual Studio. The free "community edition"
will work fine. Do a standard install for C++ development.
@@ -20,9 +20,11 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
install the TCL development libraries in the "`c:\Tcl`" directory.
Make adjustments
if you want TCL installed somewhere else. SQLite needs both the
"tclsh.exe" command-line tool as part of the build process, and
the "tcl86.lib" library in order to run tests. You will need
TCL version 8.6 or later.
"tclsh90.exe" command-line tool as part of the build process, and
the "tcl90.lib" and "tclstub.lib" libraries in order to run tests.
This document assumes you are working with <b>TCL version 9.0</b>.
See versions of this document from prior to 2024-10-10 for
instructions on how to build using TCL version 8.6.
<ol type="a">
<li>Get the TCL source archive, perhaps from
[https://www.tcl.tk/software/tcltk/download.html](https://www.tcl.tk/software/tcltk/download.html).
@@ -30,13 +32,10 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
of the source tree.
<li>Run: `nmake /f makefile.vc release`
<li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl install`
<li>CD to `c:\Tcl\lib`. In that subfolder make a copy of the
"`tcl86t.lib`" file to the alternative name "`tcl86.lib`"
(omitting the second 't'). Leave the copy in the same directory
as the original.
<li>CD to `c:\Tcl\bin`. Make a copy of the "`tclsh86t.exe`"
file into "`tclsh.exe`" (without the "86t") in the same directory.
<li>Add `c:\Tcl\bin` to your %PATH%. To do this, go to Settings
<li><i>Optional:</i> CD to `c:\Tcl\bin` and make a copy of
`tclsh90.exe` over into just `tclsh.exe`.
<li><i>Optional:</i>
Add `c:\Tcl\bin` to your %PATH%. To do this, go to Settings
and search for "path". Select "edit environment variables for
your account" and modify your default PATH accordingly.
You will need to close and reopen your command prompts after
@@ -59,6 +58,7 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
<li> `nmake /f makefile.msc sqlite3.c`
<li> `nmake /f makefile.msc sqlite3.exe`
<li> `nmake /f makefile.msc sqldiff.exe`
<li> `nmake /f makefile.msc sqlite3_rsync.exe`
<li> `nmake /f makefile.msc tclextension-install`
<li> `nmake /f makefile.msc devtest`
<li> `nmake /f makefile.msc releasetest`
@@ -127,7 +127,7 @@ nmake /f Makefile.msc sqlite3_analyzer.exe
~~~~
And you will end up with a working executable. However, that executable
will depend on having the "tcl86.dll" library somewhere on your %PATH%.
will depend on having the "tcl98.dll" library somewhere on your %PATH%.
Use the following steps to build an executable that has the TCL library
statically linked so that it does not depend on separate DLL:
@@ -137,27 +137,26 @@ statically linked so that it does not depend on separate DLL:
2. Untar the TCL source tarball into a fresh directory. CD into
the "win/" subfolder.
3. Run: `nmake /f makefile.vc OPTS=nothreads,static shell`
3. Run: `nmake /f makefile.vc OPTS=static shell`
4. CD into the "Release*" subfolder that is created (note the
wildcard - the full name of the directory might vary). There
you will find the "tcl86s.lib" file. Copy this file into the
same directory that you put the "tcl86.lib" on your initial
you will find the "tcl90s.lib" file. Copy this file into the
same directory that you put the "tcl90.lib" on your initial
installation. (In this document, that directory is
"`C:\Tcl32\lib`" for 32-bit builds and
"`C:\Tcl\lib`" for 64-bit builds.)
5. CD into your SQLite source code directory and build the desired
utility program, but add the following extra arguments to the
utility program, but add the following extra argument to the
nmake command line:
<blockquote><pre>
CCOPTS="-DSTATIC_BUILD" LIBTCL="tcl86s.lib netapi32.lib user32.lib"
STATICALLY_LINK_TCL=1
</pre></blockquote>
<p>So, for example, to build a statically linked version of
sqlite3_analyzer.exe, you might type:
<blockquote><pre>
nmake /f Makefile.msc CCOPTS="-DSTATIC_BUILD" LIBTCL="tcl86s.lib netapi32.lib user32.lib" sqlite3_analyzer.exe
nmake /f Makefile.msc STATICALLY_LINK_TCL=1 sqlite3_analyzer.exe
</pre></blockquote>
6. After your executable is built, you can verify that it does not
+74
View File
@@ -402,6 +402,19 @@ do_setup_rec_test $tn.19.0 {
SCAN t1 USING COVERING INDEX t1_idx_01a7214e
}
ifcapable fts5 {
do_setup_rec_test $tn.20.0 {
CREATE VIRTUAL TABLE ft USING fts5(a);
CREATE TABLE t1(x, y);
} {
SELECT * FROM ft, t1 WHERE a=x
} {
CREATE INDEX t1_idx_00000078 ON t1(x);
SCAN ft VIRTUAL TABLE INDEX 0:
SEARCH t1 USING INDEX t1_idx_00000078 (x=?)
}
}
}
proc do_candidates_test {tn sql res} {
@@ -507,4 +520,65 @@ do_candidates_test 6.1 {
CREATE INDEX x1_idx_00000062 ON x1(b);
}
#-------------------------------------------------------------------------
ifcapable fts5 {
reset_db
do_execsql_test 7.0 {
CREATE VIRTUAL TABLE ft USING fts5(a);
CREATE TABLE t1(x, y);
}
do_candidates_test 7.1 {
SELECT * FROM ft, t1 WHERE a=x
} {
CREATE INDEX t1_idx_00000078 ON t1(x);
}
register_tcl_module db
proc vtab_command {method args} {
global G
switch -- $method {
xConnect {
return "CREATE TABLE t1(a, b, c);"
}
xBestIndex {
return [list]
}
xFilter {
return [list sql "SELECT rowid, * FROM t0"]
}
}
return {}
}
do_execsql_test 7.2 {
CREATE TABLE t0(a, b, c);
INSERT INTO t0 VALUES(1, 2, 3), (11, 22, 33);
CREATE VIRTUAL TABLE t2 USING tcl(vtab_command);
}
do_execsql_test 7.3 {
SELECT * FROM t2
} {
1 2 3
11 22 33
}
do_candidates_test 7.4 {
SELECT * FROM ft, t1 WHERE a=x
} {
CREATE INDEX t1_idx_00000078 ON t1(x);
}
do_test 7.5 {
set expert [sqlite3_expert_new db]
list [catch { $expert sql "SELECT * FROM ft, t2 WHERE b=1" } msg] $msg
} {1 {no such table: t2}}
$expert destroy
}
finish_test
+81 -8
View File
@@ -1392,6 +1392,66 @@ static int idxProcessTriggers(sqlite3expert *p, char **pzErr){
return rc;
}
/*
** This function tests if the schema of the main database of database handle
** db contains an object named zTab. Assuming no error occurs, output parameter
** (*pbContains) is set to true if zTab exists, or false if it does not.
**
** Or, if an error occurs, an SQLite error code is returned. The final value
** of (*pbContains) is undefined in this case.
*/
static int expertDbContainsObject(
sqlite3 *db,
const char *zTab,
int *pbContains /* OUT: True if object exists */
){
const char *zSql = "SELECT 1 FROM sqlite_schema WHERE name = ?";
sqlite3_stmt *pSql = 0;
int rc = SQLITE_OK;
int ret = 0;
rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_text(pSql, 1, zTab, -1, SQLITE_STATIC);
if( SQLITE_ROW==sqlite3_step(pSql) ){
ret = 1;
}
rc = sqlite3_finalize(pSql);
}
*pbContains = ret;
return rc;
}
/*
** Execute SQL command zSql using database handle db. If no error occurs,
** set (*pzErr) to NULL and return SQLITE_OK.
**
** If an error does occur, return an SQLite error code and set (*pzErr) to
** point to a buffer containing an English language error message. Except,
** if the error message begins with "no such module:", then ignore the
** error and return as if the SQL statement had succeeded.
**
** This is used to copy as much of the database schema as possible while
** ignoring any errors related to missing virtual table modules.
*/
static int expertSchemaSql(sqlite3 *db, const char *zSql, char **pzErr){
int rc = SQLITE_OK;
char *zErr = 0;
rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
if( rc!=SQLITE_OK && zErr ){
int nErr = STRLEN(zErr);
if( nErr>=15 && memcmp(zErr, "no such module:", 15)==0 ){
sqlite3_free(zErr);
rc = SQLITE_OK;
zErr = 0;
}
}
*pzErr = zErr;
return rc;
}
static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
int rc = idxRegisterVtab(p);
@@ -1403,22 +1463,29 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
** 2) Create the equivalent virtual table in dbv.
*/
rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
"SELECT type, name, sql, 1 FROM sqlite_schema "
"SELECT type, name, sql, 1, sql LIKE 'create virtual%' "
"FROM sqlite_schema "
"WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
" UNION ALL "
"SELECT type, name, sql, 2 FROM sqlite_schema "
"SELECT type, name, sql, 2, 0 FROM sqlite_schema "
"WHERE type = 'trigger'"
" AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
"ORDER BY 4, 1"
"ORDER BY 4, 5 DESC, 1"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
int bVirtual = sqlite3_column_int(pSchema, 4);
int bExists = 0;
if( zType==0 || zName==0 ) continue;
if( zType[0]=='v' || zType[1]=='r' ){
if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
rc = expertDbContainsObject(p->dbv, zName, &bExists);
if( rc || bExists ) continue;
if( zType[0]=='v' || zType[1]=='r' || bVirtual ){
/* A view. Or a trigger on a view. */
if( zSql ) rc = expertSchemaSql(p->dbv, zSql, pzErrmsg);
}else{
IdxTable *pTab;
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
@@ -1957,12 +2024,18 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
if( rc==SQLITE_OK ){
sqlite3_stmt *pSql = 0;
rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
"SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
" AND sql NOT LIKE 'CREATE VIRTUAL %%' ORDER BY rowid"
"SELECT sql, name "
" FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
" ORDER BY rowid"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
const char *zName = (const char*)sqlite3_column_text(pSql, 1);
int bExists = 0;
rc = expertDbContainsObject(pNew->dbm, zName, &bExists);
if( rc==SQLITE_OK && zSql && bExists==0 ){
rc = expertSchemaSql(pNew->dbm, zSql, pzErrmsg);
}
}
idxFinalize(&rc, pSql);
}
+1 -1
View File
@@ -198,7 +198,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
while( zIn<zTerm && (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
if( c<0x80 \
+42 -40
View File
@@ -658,46 +658,48 @@ static int seriesBestIndex(
}
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;
if( pConstraint->iColumn<SERIES_COLUMN_START ){
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;
+90 -26
View File
@@ -31,27 +31,21 @@
#include <fcntl.h>
/*
** If the SQLITE_U8TEXT_ONLY option is defined, then only use
** _O_U8TEXT, _O_WTEXT, and similar together with the UTF-16
** interfaces to the Windows CRT. The use of ANSI-only routines
** like fputs() and ANSI modes like _O_TEXT and _O_BINARY is
** avoided.
** If the SQLITE_U8TEXT_ONLY option is defined, then use O_U8TEXT
** when appropriate on all output. (Sometimes use O_BINARY when
** rendering ASCII text in cases where NL-to-CRLF expansion would
** not be correct.)
**
** The downside of using SQLITE_U8TEXT_ONLY is that it becomes
** impossible to output a bare newline character (0x0a) - that is,
** a newline that is not preceded by a carriage return (0x0d).
** And without that capability, sometimes the output will be slightly
** incorrect, as extra 0x0d characters will have been inserted where
** they do not belong.
** If the SQLITE_U8TEXT_STDIO option is defined, then use O_U8TEXT
** when appropriate when writing to stdout or stderr. Use O_BINARY
** or O_TEXT (depending on things like the .mode and the .crlf setting
** in the CLI, or other context clues in other applications) for all
** other output channels.
**
** The SQLITE_U8TEXT_STDIO compile-time option is a compromise.
** It always enables _O_WTEXT or similar for stdin, stdout, stderr,
** but allows other streams to be _O_TEXT and/or O_BINARY. The
** SQLITE_U8TEXT_STDIO option has the same downside as SQLITE_U8TEXT_ONLY
** in that stray 0x0d characters might appear where they ought not, but
** at least with this option those characters only appear on standard
** I/O streams, and not on new streams that might be created by the
** application using sqlite3_fopen() or sqlite3_popen().
** The default behavior, if neither of the above is defined is to
** use O_U8TEXT when writing to the Windows console (or anything
** else for which _isatty() returns true) and to use O_BINARY or O_TEXT
** for all other output channels.
*/
#if defined(SQLITE_U8TEXT_ONLY)
# define UseWtextForOutput(fd) 1
@@ -67,6 +61,31 @@
# define IsConsole(fd) 1
#endif
/*
** Global variables determine if simulated O_BINARY mode is to be
** used for stdout or other, respectively. Simulated O_BINARY mode
** means the mode is usually O_BINARY, but switches to O_U8TEXT for
** unicode characters U+0080 or greater (any character that has a
** multi-byte representation in UTF-8). This is the only way we
** have found to render Unicode characters on a Windows console while
** at the same time avoiding undesirable \n to \r\n translation.
*/
static int simBinaryStdout = 0;
static int simBinaryOther = 0;
/*
** Determine if simulated binary mode should be used for output to fd
*/
static int UseBinaryWText(FILE *fd){
if( fd==stdout || fd==stderr ){
return simBinaryStdout;
}else{
return simBinaryOther;
}
}
/*
** Work-alike for the fopen() routine from the standard C library.
*/
@@ -88,6 +107,7 @@ FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
}
free(b1);
free(b2);
simBinaryOther = 0;
return fp;
}
@@ -143,13 +163,53 @@ char *sqlite3_fgets(char *buf, int sz, FILE *in){
}
}
/*
** Send ASCII text as O_BINARY. But for Unicode characters U+0080 and
** greater, switch to O_U8TEXT.
*/
static void piecemealOutput(wchar_t *b1, int sz, FILE *out){
int i;
wchar_t c;
while( sz>0 ){
for(i=0; i<sz && b1[i]>=0x80; i++){}
if( i>0 ){
c = b1[i];
b1[i] = 0;
fflush(out);
_setmode(_fileno(out), _O_U8TEXT);
fputws(b1, out);
fflush(out);
b1 += i;
b1[0] = c;
sz -= i;
}else{
fflush(out);
_setmode(_fileno(out), _O_TEXT);
_setmode(_fileno(out), _O_BINARY);
fwrite(&b1[0], 1, 1, out);
for(i=1; i<sz && b1[i]<0x80; i++){
fwrite(&b1[i], 1, 1, out);
}
fflush(out);
_setmode(_fileno(out), _O_U8TEXT);
b1 += i;
sz -= i;
}
}
}
/*
** Work-alike for fputs() from the standard C library.
*/
int sqlite3_fputs(const char *z, FILE *out){
if( UseWtextForOutput(out) ){
if( !UseWtextForOutput(out) ){
/* Writing to a file or other destination, just write bytes without
** any translation. */
return fputs(z, out);
}else{
/* When writing to the command-prompt in Windows, it is necessary
** to use _O_WTEXT input mode and write UTF-16 characters.
** to use O_U8TEXT to render Unicode U+0080 and greater. Go ahead
** use O_U8TEXT for everything in text mode.
*/
int sz = (int)strlen(z);
wchar_t *b1 = malloc( (sz+1)*sizeof(wchar_t) );
@@ -157,13 +217,13 @@ int sqlite3_fputs(const char *z, FILE *out){
sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz);
b1[sz] = 0;
_setmode(_fileno(out), _O_U8TEXT);
fputws(b1, out);
if( UseBinaryWText(out) ){
piecemealOutput(b1, sz, out);
}else{
fputws(b1, out);
}
sqlite3_free(b1);
return 0;
}else{
/* Writing to a file or other destination, just write bytes without
** any translation. */
return fputs(z, out);
}
}
@@ -205,6 +265,10 @@ void sqlite3_fsetmode(FILE *fp, int mode){
if( !UseWtextForOutput(fp) ){
fflush(fp);
_setmode(_fileno(fp), mode);
}else if( fp==stdout || fp==stderr ){
simBinaryStdout = (mode==_O_BINARY);
}else{
simBinaryOther = (mode==_O_BINARY);
}
}
+4 -4
View File
@@ -744,7 +744,7 @@ static const char *recoverUnusedString(
}
/*
** Implementation of scalar SQL function "escape_crnl". The argument passed to
** Implementation of scalar SQL function "escape_crlf". The argument passed to
** this function is the output of built-in function quote(). If the first
** character of the input is "'", indicating that the value passed to quote()
** was a text value, then this function searches the input for "\n" and "\r"
@@ -755,7 +755,7 @@ static const char *recoverUnusedString(
** Or, if the first character of the input is not "'", then a copy of the input
** is returned.
*/
static void recoverEscapeCrnl(
static void recoverEscapeCrlf(
sqlite3_context *context,
int argc,
sqlite3_value **argv
@@ -970,7 +970,7 @@ static int recoverOpenOutput(sqlite3_recover *p){
{ "getpage", 1, recoverGetPage },
{ "page_is_used", 1, recoverPageIsUsed },
{ "read_i32", 2, recoverReadI32 },
{ "escape_crnl", 1, recoverEscapeCrnl },
{ "escape_crlf", 1, recoverEscapeCrlf },
};
const int flags = SQLITE_OPEN_URI|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
@@ -1323,7 +1323,7 @@ static sqlite3_stmt *recoverInsertStmt(
if( bSql ){
zBind = recoverMPrintf(p,
"%z%sescape_crnl(quote(?%d))", zBind, zSqlSep, pTab->aCol[ii].iBind
"%z%sescape_crlf(quote(?%d))", zBind, zSqlSep, pTab->aCol[ii].iBind
);
zSqlSep = "||', '||";
}else{
+3 -3
View File
@@ -569,7 +569,7 @@ dbhash$(EXE): $(TOP)/tool/dbhash.c sqlite3.c sqlite3.h
$(TOP)/tool/dbhash.c sqlite3.c $(TLIBS) $(THREADLIB)
RSYNC_SRC = \
$(TOP)/tool/sqlite3-rsync.c \
$(TOP)/tool/sqlite3_rsync.c \
sqlite3.c
RSYNC_OPT = \
@@ -578,7 +578,7 @@ RSYNC_OPT = \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED
sqlite3-rsync$(EXE): $(RSYNC_SRC)
sqlite3_rsync$(EXE): $(RSYNC_SRC)
$(TCC) -o $@ $(RSYNC_OPT) $(RSYNC_SRC) $(TLIBS)
scrub$(EXE): $(TOP)/ext/misc/scrub.c sqlite3.o
@@ -1159,7 +1159,7 @@ clean:
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) sqlite3-rsync$(TEXE)
rm -f sqlite3_analyzer$(TEXE) sqlite3_rsync$(TEXE)
rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
rm -f threadtest5$(TEXE)
+41 -39
View File
@@ -1,11 +1,11 @@
C Add\ssqlite3rc.h\sbuild.
D 2024-10-09T13:26:01.411
C Merge\strunk\sinto\sthis\sbranch.
D 2024-10-16T13:02:07.918
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in e09c278841effbb93503fe3846337350bebc215f06c63f2c998e8cce7b109e8b
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc 9c6d80d9d103fa42e931f4c464884a5e577fae8563acc7589bff4e43fbe8f864
F Makefile.msc 58b69eda1faad5d475092b8aeffab9156ee4901a82db089b166607f2ec907ee4
F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -18,20 +18,20 @@ F auto.def 42b2334f320fafcebb09673453fc9df470839e136d84ddeb74699af16b08b056
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am adedc1324b6a87fdd1265ddd336d2fb7d4f36a0e77b86ea553ae7cc4ea239347
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
F autoconf/Makefile.msc 2aced6442addab13ed115696eba28d9ed29caa3dd604a31392c2c7a5da301492
F autoconf/Makefile.msc 0a1fdef1f2c618815cf7c82c817a7369c1e07b3cfed490803db16fb43326d506
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
F autoconf/tea/Makefile.in 106a96f2f745d41a0f6193f1de98d7355830b65d45032c18cd7c90295ec24196
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/README.txt 94fa2472d3ee4139ab24b364d99a70445d0a25531dac3ce03af2055d581f76b4 w autoconf/tea/README
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
F autoconf/tea/configure.ac 0deb5d6c49c8119f75f436488219fc043127d72057af5dfba2c9ce096a5734bc
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in b9eb6dd37f64e08e637d576b3c83259814b9cddd78bec4af2e5abfc6c5c750ce
F autoconf/tea/pkgIndex.tcl.in 55aec3c6d7e9a1de9b8d2fdc9c27fd055da3ac3a51b572195e2ae7300bcfd3a2
F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00
F autoconf/tea/tclconfig/tcl.m4 c6e5f2fc7178f40d087403daa044ef3b86a8e30793f3b121bdcbdf152c6a776a
F autoconf/tea/win/makefile.vc 2c478a9a962e48b2bf9062734e04d7c63c556e217095419173f9d7938d7d78f7
F autoconf/tea/win/makefile.vc 9b33af4214a5c8360549b96380f55ece1a2df76a51ab4c726296e5c43d8a2227
F autoconf/tea/win/nmakehlp.c b01f822eabbe1ed2b64e70882d97d48402b42d2689a1ea00342d1a1a7eaa19cb
F autoconf/tea/win/rules.vc 7b3bb2ef32ade0f3f14d951231811678722725e3bca240dd9727ae0dfe10f6a5
F autosetup/LICENSE 41a26aebdd2cd185d1e2b210f71b7ce234496979f6b35aef2cbf6b80cbed4ce4
@@ -55,10 +55,11 @@ F autosetup/tmake.tcl a275793ec1b6f8708179af0acef1f6f10d46c2920739743f7a8720c6d7
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
F configure.ac 934d33880d4c7dbff05c2ebaa3820e344e1321d5fff6d6393963e50c3a613e40
F configure.ac 6bb3470ed862e753a5e6754cc0eea16e1de7e8c6aac458de1ee7706a8da26f19
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/compile-for-windows.md 4d4bfafda42a7a33f166d23aed4db1bb4ea1e5751595a5cced2bad349fd14652
F doc/compile-for-unix.md 90f17554cc3d19b2dae8142b5aeda1a8890692d5f2e091ed4a6f9b46b8f10f62
F doc/compile-for-windows.md a9ab9f6c49763d63d177a386a9e53ee670101f80e8bcb73cafca438156229076
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b
F doc/lemon.html 8b266ff711d2ec7f867c3dca37634963f48a630329908cc282beebfa8c708706
@@ -76,8 +77,8 @@ F ext/consio/console_io.c d2b74afae8d301de2e8447b1045fcd33eb59df13bf581d906d99c7
F ext/consio/console_io.h b5ebe34aa15b357621ebbea3d3f2e2b24750d4280b5802516409e23947fd9ee5
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
F ext/expert/expert1.test b10f9e20f64102a015c0fcf54cb7b7680266b397e91d93cdad45f57857cdfba6
F ext/expert/sqlite3expert.c df417a6d91873a74d35daa9259171647c23c6601415e938e8a71702703f3d677
F ext/expert/expert1.test 1fa0201d8610883c32214b1d83e3a6cc582694ac1067be8319b280235145a555
F ext/expert/sqlite3expert.c b7cbbd7cc109c66ebdf6091467d790abb9d7c25ae3b822bb76388509641d37de
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c b767b2039a0df707eb3147e86bcf68b252d8455d9a41774b1a836cd052ceca70
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
@@ -124,7 +125,7 @@ F ext/fts5/fts5_storage.c 337b05e4c66fc822d031e264d65bde807ec2fab08665ca2cc8aaf9
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
F ext/fts5/fts5_tokenize.c 033e2e43b8e852c0ef6cecc611266d61e2346e52ec7dcfb76a428fe56a07efa9
F ext/fts5/fts5_unicode2.c 6f9b0fb79a8facaed76628ffd4eb9c16d7f2b84b52872784f617cf3422a9b043
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
F ext/fts5/fts5_vocab.c e4830b00809e5da53bc10f93adc59e321407b0f801c7f4167c0e47f5552267e0
@@ -440,13 +441,13 @@ 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 a6089b5e8e3002bd1e5d9877cee6aead0b9a6426e406c09a399817db9e9ae823
F ext/misc/series.c 596afbfbbc81ccf4ea6da11f016f7eed630ed195b5e9d548117e19f06d63f641
F ext/misc/sha1.c cb5002148c2661b5946f34561701e9105e9d339b713ec8ac057fd888b196dcb9
F ext/misc/shathree.c 1821d90a0040c9accdbe3e3527d378d30569475d758aa70f6848924c0b430e8c
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c bcc42ef3fd29429bc01a83e751332b8d4690e65d45008449bdffe7656371487f
F ext/misc/sqlar.c a6175790482328171da47095f87608b48a476d4fac78d8a9ff18b03a2454f634
F ext/misc/sqlite3_stdio.c f110e6f2dc97c67e89f941f82af7dbd221193fa44d1e3ef38a691454a2cbccda
F ext/misc/sqlite3_stdio.c 73192f75e1e89722fbdf209056a562ca2a35df3c9e998f9270331e03cb621e7a
F ext/misc/sqlite3_stdio.h f05eaf5e0258f0573910324a789a9586fc360a57678c57a6d63cfaa2245b6176
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
@@ -527,7 +528,7 @@ F ext/recover/recoverpgsz.test 88766fcb810e52ee05335c456d4e5fb06d02b73d3ccb48c52
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
F ext/recover/sqlite3recover.c 2dcf6b56c5e0e2b43fc4c6115b689ab194c374ced7f7f8380ad9a24d8ef24ac9
F ext/recover/sqlite3recover.c e822ecbb05a04a5c85d1309765fcd6cf392d100d02d2227cd7720c9d6921a17a
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c 072260d7452a3b81aba995b2b3269e7ec2aa7f06725544ba4c25b1b0a1dbc61a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -708,7 +709,7 @@ F ext/wasm/wasmfs.make bc8bb227f35d5bd3863a7bd2233437c37472a0d81585979f058f9b9b5
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk 0a55ebec3508ca1bdb593d86f3aa19d7fa42a2ddd3220703e6dc0a65f1338a43
F main.mk c6501abe2d915ed1a2ec3d074e652c096177f93c50ac91f815c831e3417f9019
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -738,10 +739,10 @@ F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
F src/dbpage.c db1be8adaf1f839ad733c08baeac5c22aa912f7b535865c0c061382602081360
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239
F src/expr.c a9d9f5fdfbdd3b2c94d7af1b11f181464b8a641736cf32cb92fa3c5e7ecb30df
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c df400a1d3f4625997d4dd8a81951c303e066277c29b861d37e03cd152d7858dd
F src/func.c 1d093b93b8f097665721e59a1c404d7db4dc591e1a777a7a1022dfbda21e108b
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
@@ -772,7 +773,7 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
F src/os_unix.c 779e83666ecd535f6725497ba6da069c1d15138ff6a4ee123edad1ae0cdfbe83
F src/os_unix.c 14d0f80e4779f5f76bcc71e7af97e3efe318fa3d0b22335623c59fab7d39302b
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3
@@ -781,23 +782,23 @@ F src/parse.y a7a8d42eeff01d267444ddb476029b0b1726fb70ae3d77984140f17ad02e2d61
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
F src/pragma.c 52bfbf6dfd668b69b5eb9bd1186e3a67367c8453807150d6e75239229924f684
F src/pragma.c cd613126f7cdd0c2ded4648c3c7b7b0239e678d7f3489e88c4b6d6858372fd07
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 3ba0ad907b7773ed642f66cea8a2c9c8edc18841aa1050b6218dbb3479e86225
F src/printf.c 6a87534ebfb9e5346011191b1f3a7ebc457f5938c7e4feeea478ecf53f6a41b2
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 9750a281f7ba073b4e6da2be1a6c4071f5d841a7746c5fb3f70d6d793b6675ea
F src/resolve.c c8a5372b97b2a2e972a280676f06ddb5b74e885d3b1f5ce383f839907b57ef68
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4b14337a2742f0c0beeba490e9a05507e9b4b12184b9cd12773501d08d48e3fe
F src/shell.c.in 981efe98f98a983c1d0193d18528eb2d765207c0c82b67b610be60f17995a43e
F src/sqlite.h.in 1def838497ad53c81486649ce79821925d1ac20a9843af317a344d507efe116e
F src/shell.c.in 0662f9bcf0725461778d0254a06150e5d61c08c5a87a7281ccdf45552050c79d
F src/sqlite.h.in add9e064d6b42af8f1a4a3322bddadec76696e520aedebd83e0d3211c15ac999
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
F src/sqliteInt.h 989dca8b25ca11f5c52e5a457cc500042c43b0b3e5fea9a12d9020d0350722cd
F src/sqliteInt.h ad02397dc4d22b77f9a331412d46e4c1e49459dd386fba8373fa148998e1e7d0
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c c6888598f08dee3d9112a38ef42c8f5c89ca7f3190f4694744d0b84250f4bf8c
F src/tclsqlite.c e2b752dd08034c834e3639afa3300940d6e847fcd94207e1f2f1b83ce08b87be
F src/tclsqlite.h c6af51f31a2b2172d674608763a4b98fdf5cd587e4025053e546fb8077757262
F src/test1.c 8bf8b74145b768f42386787f93f6d6dad7bc400a4ee2d50e4ad5a06a20a97ef1
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
@@ -855,7 +856,7 @@ F src/treeview.c 88aa39b754f5ef7214385c1bbbdd2f3dc20efafeed0cf590e8d1199b9c6e44a
F src/trigger.c 0bb986a5b96047fd597c6aac28588853df56064e576e6b81ba777ef2ccaac461
F src/update.c 0e01aa6a3edf9ec112b33eb714b9016a81241497b1fb7c3e74332f4f71756508
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7bc550af6f3ddd5f5dc82d092c41f728acb760c92e0b47f391963b01ae52569b
F src/utf.c 8b29d9a5956569ea2700f869669b8ef67a9662ee5e724ff77ab3c387e27094ba
F src/util.c 4d57ae861d0e234019be9596818228d7715e44e6efaccb612cf4498bedc2e023
F src/vacuum.c b763b6457bd058d2072ef9364832351fd8d11e8abf70cbb349657360f7d55c40
F src/vdbe.c be5f58bc29f60252e041a618eae59e8d57d460ba136c5403cf0abf955560c457
@@ -873,10 +874,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c a0d42bfdef935e1389737152394d08e59e7c48697f40a9fc2e0552cb19dc731f
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c 461d41017d900d4248a268df96d2d30506c4dcc2257f4167c4f46072003ce2cf
F src/where.c 12fe24880901997372b88fd7ca9a21457404ad35201712c02cc57978578abb10
F src/whereInt.h a5d079c346a658b7a6e9e47bb943d021e02fa1e6aed3b964ca112112a4892192
F src/wherecode.c 5172d647798134e7c92536ddffe7e530c393d79b5dedd648b88faf2646c65baf
F src/whereexpr.c 44f41ae554c7572e1de1485b3169b233ee04d464b2ee5881687ede3bf07cacfa
F src/whereexpr.c 0f93a29cabd3a338d09a1f5c6770620a1ac51ec1157f3229502a7e7767c60b6f
F src/window.c 499d48f315a09242dc68f2fac635ed27dcf6bbb0d9ab9084857898c64489e975
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@@ -1061,7 +1062,7 @@ F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test ac13504593d89d69690d45479547616ed12644d42b5cb7eeb2e759a76fc23dcb
F test/corruptL.test 652fc8ac0763a6fd3eb28b951d481924167b2d9936083bcc68253b2274a0c8fe
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
F test/corruptN.test 7c099d153a554001b4fb829c799b01f2ea6276cbc32479131e0db0da4efd9cc4
F test/corruptN.test 40bc47aee4af9aadff902be43f14d69dc17b3731448dad6c7cc722da913f1455
F test/cost.test cc434a026b1e9d0d98137a147e24e5daf1b1ad09e9ff7da63b34c83ddd136d92
F test/count.test cd4bd531066e8d77ef8fe1e3fc8253d042072e117ccab214b290cf83f1602249
F test/countofview.test 4088e461a10ee33e69803c177a69aa1d7bba81a9ffc2df66d76465a22ca7fdfc
@@ -1343,6 +1344,7 @@ F test/indexA.test 11d84f6995e6e5b9d8315953fb1b6d29772ee7c7803ee9112715e7e4dd3e4
F test/indexedby.test f21eca4f7a6ffe14c8500a7ad6cd53166666c99e5ccd311842a28bc94a195fe0
F test/indexexpr1.test 24fa85a12da384dd1d56f7b24e593c51a8a54b4c5e2e8bbb9e5fdf1099427faf
F test/indexexpr2.test 1c382e81ef996d8ae8b834a74f2a9013dddf59214c32201d7c8a656d739f999a
F test/indexexpr3.test 9d893bf440937ebcc1e59c7c9c1505c40c918346a3ddde76a69078f3c733c45d
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 4e3f0de67aac3c5be1f4aaedbcea11638f1b5cdc9a3115be14d19aa9db7623c6
@@ -1409,7 +1411,7 @@ F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/lemon-test01.y 70110eff607ab137ccc851edb2bc7e14a6d4f246b5d2d25f82a60b69d87a9ff2
F test/like.test 242ee7f5d08a031144c0daf63bbd7e7710c847ccf387a83347e0b61b3aa69526
F test/like.test b3ea2ba3558199aa8f25a42ddeb54772e234fab50868c9f066047acdbda8fc58
F test/like2.test d3be15fefee3e02fc88942a9b98f26c5339bbdef7783c90023c092c4955fe3d3
F test/like3.test a76e5938fadbe6d32807284c796bafd869974a961057bc5fc5a28e06de98745c
F test/limit.test 350f5d03c29e7dff9a2cde016f84f8d368d40bcd02fa2b2a52fa10c4bf3cbfaf
@@ -1423,7 +1425,7 @@ F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
F test/lock4.test 27143363eda1622f03c133efc8db808fc331afd973486cb571ea71cd717d37b8
F test/lock5.test 24693e40a805f71d80836f720d1f2034684a39b64f1e1990989002c7968c11ee
F test/lock5.test 583cae05992af0f66607286917f7d5f8aed3b6053c52df5994efb98f2a8fdbaf
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
F test/lock_common.tcl 2f3f7f2e9637f93ccf609df48ef5b27a50278b6b1cd752b445d52262e5841413
@@ -1647,7 +1649,7 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test b02d628494fa284cdb2b7b2fecdadea96913796afd623f340a79d68f055dcb7e
F test/shell1.test 5d84e415adf7cc4edd5913c4f23c761104ff135b9c190fcf7b430a4cbca6cb65
F test/shell2.test 01a01f76ed98088ce598794fbf5b359e148271541a8ddbf79d21cc353cc67a24
F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8
F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
@@ -1746,7 +1748,7 @@ F test/thread005.test 50d10b5684399676174bd96c94ad4250b1a2c8b6
F test/thread1.test df115faa10a4ba1d456e9d4d9ec165016903eae4
F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
F test/thread3.test a12656a56cdf67acb6a2ff7638826c6d6a645f79909d86df521045ad31cf547d
F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
F test/thread_common.tcl b3b19a769fe30ef5537cdfa60acd49b78f771301627720d1add2d3bac77d9039
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
F test/threadtest3.c 655bff6c0895ec03f014126aa65e808fac9aae8c5a7a7da58a510cbe8b43b781
@@ -2168,7 +2170,7 @@ F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6
F tool/mksqlite3c.tcl c6acfdf4e4ef93478ff3ce3cd593e17abb03f446036ce710c3156bcfa18665e0
F tool/mksqlite3h.tcl d391cff7cad0a372ee1406faee9ccc7dad9cb80a0c95cae0f73d10dd26e06762
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mktoolzip.tcl c7a9b685f5131d755e7d941cec50cee7f34178b9e34c9a89811eeb08617f8423
F tool/mktoolzip.tcl 1b3383c6cd1ca3e1bfdf157d1383f29d6264b9600c381e682789c83617dc1014
F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e540a
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
@@ -2196,11 +2198,11 @@ F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
F tool/sqldiff.c 2a0987d183027c795ced13d6749061c1d2f38e24eddb428f56fa64c3a8f51e4b
F tool/sqlite3-rsync.c 2f06f02ee3a28f847b3fb8c0f32e3b3296571e0f8027939b95d32df5edfe1dd9
F tool/sqlite3_analyzer.c.in 348ba349bbdc93c9866439f9f935d7284866a2a4e6898bc906ae1204ade56918
F tool/sqlite3_rsync.c 2a2b79a0463d400696aa9429be5c0ddec6b1f7ceefa5fed7acfdc859a435221f w tool/sqlite3-rsync.c
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f
F tool/src-verify.c d00f93263aa2fa6ba0cba0106d95458e6effb94fdb5fc634f56834f90c05bbb4
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
F tool/srctree-check.tcl c15f860a3c97d5f7b4c14b60392d9466af29dd006c4ef18127f502641e2977a8
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
@@ -2236,8 +2238,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 292ad7d519d39f16f130d082d3f134deadd5409d56ffb5340064a1996f4b4d57
R b2998251d1a1c77a7b55806ea3c31919
P 8d5f99f7e3f0ff9eaea1cb550369864e49a0fe0b00a53b1eba6ed099b61d8d24 86e794cbaa5ae600635c933b46298a39f2465daf4c5cd1570f2a03e19ac08d9d
R 0f51619208545f999beb801583f35ef3
U stephan
Z 2c5ae792bbaf5eea557dff2e61da4cd7
Z b40f13e331b5567249a3bbe5622b7fa3
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
8d5f99f7e3f0ff9eaea1cb550369864e49a0fe0b00a53b1eba6ed099b61d8d24
9c3bb3dc4f5b5cd7db6cd50d22dbe8f933cccf5f2fd253467bb50f36b3207a93
+64
View File
@@ -4554,6 +4554,59 @@ static int exprCodeInlineFunction(
return target;
}
/*
** Expression Node callback for sqlite3ExprCanReturnSubtype().
**
** Only a function call is able to return a subtype. So if the node
** is not a function call, return WRC_Prune immediately.
**
** A function call is able to return a subtype if it has the
** SQLITE_RESULT_SUBTYPE property.
**
** Assume that every function is able to pass-through a subtype from
** one of its argument (using sqlite3_result_value()). Most functions
** are not this way, but we don't have a mechanism to distinguish those
** that are from those that are not, so assume they all work this way.
** That means that if one of its arguments is another function and that
** other function is able to return a subtype, then this function is
** able to return a subtype.
*/
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
int n;
FuncDef *pDef;
sqlite3 *db;
if( pExpr->op!=TK_FUNCTION ){
return WRC_Prune;
}
assert( ExprUseXList(pExpr) );
db = pWalker->pParse->db;
n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0;
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
pWalker->eCode = 1;
return WRC_Prune;
}
return WRC_Continue;
}
/*
** Return TRUE if expression pExpr is able to return a subtype.
**
** A TRUE return does not guarantee that a subtype will be returned.
** It only indicates that a subtype return is possible. False positives
** are acceptable as they only disable an optimization. False negatives,
** on the other hand, can lead to incorrect answers.
*/
static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = pParse;
w.xExprCallback = exprNodeCanReturnSubtype;
sqlite3WalkExpr(&w, pExpr);
return w.eCode;
}
/*
** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr.
** If it is, then resolve the expression by reading from the index and
@@ -4586,6 +4639,17 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
continue;
}
/* Functions that might set a subtype should not be replaced by the
** value taken from an expression index if they are themselves an
** argument to another scalar function or aggregate.
** https://sqlite.org/forum/forumpost/68d284c86b082c3e */
if( ExprHasProperty(pExpr, EP_SubtArg)
&& sqlite3ExprCanReturnSubtype(pParse, pExpr)
){
continue;
}
v = pParse->pVdbe;
assert( v!=0 );
if( p->bMaybeNullRow ){
+87 -3
View File
@@ -2535,7 +2535,13 @@ static void signFunc(
** Implementation of fpdecode(x,y,z) function.
**
** x is a real number that is to be decoded. y is the precision.
** z is the maximum real precision.
** z is the maximum real precision. Return a string that shows the
** results of the sqlite3FpDecode() function.
**
** Used for testing and debugging only, specifically testing and debugging
** of the sqlite3FpDecode() function. This SQL function does not appear
** in production builds. This function is not an API and is subject to
** modification or removal in future versions of SQLite.
*/
static void fpdecodeFunc(
sqlite3_context *context,
@@ -2562,6 +2568,82 @@ static void fpdecodeFunc(
}
#endif /* SQLITE_DEBUG */
#ifdef SQLITE_DEBUG
/*
** Implementation of parseuri(uri,flags) function.
**
** Required Arguments:
** "uri" The URI to parse.
** "flags" Bitmask of flags, as if to sqlite3_open_v2().
**
** Additional arguments beyond the first two make calls to
** sqlite3_uri_key() for integers and sqlite3_uri_parameter for
** anything else.
**
** The result is a string showing the results of calling sqlite3ParseUri().
**
** Used for testing and debugging only, specifically testing and debugging
** of the sqlite3ParseUri() function. This SQL function does not appear
** in production builds. This function is not an API and is subject to
** modification or removal in future versions of SQLite.
*/
static void parseuriFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
sqlite3_str *pResult;
const char *zVfs;
const char *zUri;
unsigned int flgs;
int rc;
sqlite3_vfs *pVfs = 0;
char *zFile = 0;
char *zErr = 0;
if( argc<2 ) return;
pVfs = sqlite3_vfs_find(0);
assert( pVfs );
zVfs = pVfs->zName;
zUri = (const char*)sqlite3_value_text(argv[0]);
if( zUri==0 ) return;
flgs = (unsigned int)sqlite3_value_int(argv[1]);
rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
pResult = sqlite3_str_new(0);
if( pResult ){
int i;
sqlite3_str_appendf(pResult, "rc=%d", rc);
sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0);
sqlite3_str_appendf(pResult, ", err=%Q", zErr);
sqlite3_str_appendf(pResult, ", file=%Q", zFile);
if( zFile ){
const char *z = zFile;
z += sqlite3Strlen30(z)+1;
while( z[0] ){
sqlite3_str_appendf(pResult, ", %Q", z);
z += sqlite3Strlen30(z)+1;
}
for(i=2; i<argc; i++){
const char *zArg;
if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
int k = sqlite3_value_int(argv[i]);
sqlite3_str_appendf(pResult, ", '%d:%q'",k,sqlite3_uri_key(zFile, k));
}else if( (zArg = (const char*)sqlite3_value_text(argv[i]))!=0 ){
sqlite3_str_appendf(pResult, ", '%q:%q'",
zArg, sqlite3_uri_parameter(zFile,zArg));
}else{
sqlite3_str_appendf(pResult, ", NULL");
}
}
}
sqlite3_result_text(ctx, sqlite3_str_finish(pResult), -1, sqlite3_free);
}
sqlite3_free_filename(zFile);
sqlite3_free(zErr);
}
#endif /* SQLITE_DEBUG */
/*
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
@@ -2624,7 +2706,8 @@ void sqlite3RegisterBuiltinFunctions(void){
WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(subtype, 1, 0, 0, subtypeFunc,
SQLITE_FUNC_TYPEOF|SQLITE_SUBTYPE),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
FUNCTION2(octet_length, 1, 0, 0, bytelengthFunc,SQLITE_FUNC_BYTELEN),
FUNCTION(instr, 2, 0, 0, instrFunc ),
@@ -2635,6 +2718,7 @@ void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(abs, 1, 0, 0, absFunc ),
#ifdef SQLITE_DEBUG
FUNCTION(fpdecode, 3, 0, 0, fpdecodeFunc ),
FUNCTION(parseuri, -1, 0, 0, parseuriFunc ),
#endif
#ifndef SQLITE_OMIT_FLOATING_POINT
FUNCTION(round, 1, 0, 0, roundFunc ),
@@ -2729,7 +2813,7 @@ void sqlite3RegisterBuiltinFunctions(void){
MFUNCTION(sqrt, 1, sqrt, math1Func ),
MFUNCTION(radians, 1, degToRad, math1Func ),
MFUNCTION(degrees, 1, radToDeg, math1Func ),
FUNCTION(pi, 0, 0, 0, piFunc ),
MFUNCTION(pi, 0, 0, piFunc ),
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
FUNCTION(sign, 1, 0, 0, signFunc ),
INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
+20 -41
View File
@@ -2464,54 +2464,33 @@ static int robust_flock(int fd, int op){
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
int rc = SQLITE_OK;
int reserved = 0;
#ifdef SQLITE_DEBUG
unixFile *pFile = (unixFile*)id;
#else
UNUSED_PARAMETER(id);
#endif
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
assert( pFile->eFileLock<=SHARED_LOCK );
/* Check if a thread in this process holds such a lock */
if( pFile->eFileLock>SHARED_LOCK ){
reserved = 1;
}
/* The flock VFS only ever takes exclusive locks (see function flockLock).
** Therefore, if this connection is holding any lock at all, no other
** connection may be holding a RESERVED lock. So set *pResOut to 0
** in this case.
**
** Or, this connection may be holding no lock. In that case, set *pResOut to
** 0 as well. The caller will then attempt to take an EXCLUSIVE lock on the
** db in order to roll the hot journal back. If there is another connection
** holding a lock, that attempt will fail and an SQLITE_BUSY returned to
** the user. With other VFS, we try to avoid this, in order to allow a reader
** to proceed while a writer is preparing its transaction. But that won't
** work with the flock VFS - as it always takes EXCLUSIVE locks - so it is
** not a problem in this case. */
*pResOut = 0;
/* Otherwise see if some other process holds it. */
if( !reserved ){
/* attempt to get the lock */
int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
if( !lrc ){
/* got the lock, unlock it */
lrc = robust_flock(pFile->h, LOCK_UN);
if ( lrc ) {
int tErrno = errno;
/* unlock failed with an error */
lrc = SQLITE_IOERR_UNLOCK;
storeLastErrno(pFile, tErrno);
rc = lrc;
}
} else {
int tErrno = errno;
reserved = 1;
/* someone else might have it reserved */
lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( IS_LOCK_ERROR(lrc) ){
storeLastErrno(pFile, tErrno);
rc = lrc;
}
}
}
OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
if( (rc & 0xff) == SQLITE_IOERR ){
rc = SQLITE_OK;
reserved=1;
}
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
*pResOut = reserved;
return rc;
return SQLITE_OK;
}
/*
+1
View File
@@ -1761,6 +1761,7 @@ void sqlite3Pragma(
/* Make sure sufficient number of registers have been allocated */
sqlite3TouchRegister(pParse, 8+cnt);
sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt);
sqlite3ClearTempRegCache(pParse);
/* Do the b-tree integrity checks */
+18
View File
@@ -1183,6 +1183,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
}
#endif
/* If the function may call sqlite3_value_subtype(), then set the
** EP_SubtArg flag on all of its argument expressions. This prevents
** where.c from replacing the expression with a value read from an
** index on the same expression, which will not have the correct
** subtype. Also set the flag if the function expression itself is
** an EP_SubtArg expression. In this case subtypes are required as
** the function may return a value with a subtype back to its
** caller using sqlite3_result_value(). */
if( (pDef->funcFlags & SQLITE_SUBTYPE)
|| ExprHasProperty(pExpr, EP_SubtArg)
){
int ii;
for(ii=0; ii<n; ii++){
ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
}
}
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
/* For the purposes of the EP_ConstFunc flag, date and time
** functions and other functions that change slowly are considered
+60 -54
View File
@@ -1448,6 +1448,7 @@ struct ShellState {
u8 bSafeMode; /* True to prohibit unsafe operations */
u8 bSafeModePersist; /* The long-term value of bSafeMode */
u8 eRestoreState; /* See comments above doAutoDetectRestore() */
u8 crlfMode; /* Do NL-to-CRLF translations when enabled (maybe) */
ColModeOpts cmOpts; /* Option values affecting columnar mode output */
unsigned statsOn; /* True to display memory stats before each finalize */
unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */
@@ -1628,13 +1629,7 @@ static const char *modeDescr[] = {
#define SEP_Tab "\t"
#define SEP_Space " "
#define SEP_Comma ","
#ifdef SQLITE_U8TEXT_ONLY
/* With the SQLITE_U8TEXT_ONLY option, the output will always be in
** text mode. The \r will be inserted automatically. */
# define SEP_CrLf "\n"
#else
# define SEP_CrLf "\r\n"
#endif
#define SEP_CrLf "\r\n"
#define SEP_Unit "\x1F"
#define SEP_Record "\x1E"
@@ -1719,7 +1714,7 @@ static void editFunc(
char *zCmd = 0;
int bBin;
int rc;
int hasCRNL = 0;
int hasCRLF = 0;
FILE *f = 0;
sqlite3_int64 sz;
sqlite3_int64 x;
@@ -1764,7 +1759,7 @@ static void editFunc(
}else{
const char *z = (const char*)sqlite3_value_text(argv[0]);
/* Remember whether or not the value originally contained \r\n */
if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
if( z && strstr(z,"\r\n")!=0 ) hasCRLF = 1;
x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
}
fclose(f);
@@ -1809,7 +1804,7 @@ static void editFunc(
sqlite3_result_blob64(context, p, sz, sqlite3_free);
}else{
sqlite3_int64 i, j;
if( hasCRNL ){
if( hasCRLF ){
/* If the original contains \r\n then do no conversions back to \n */
}else{
/* If the file did not originally contain \r\n then convert any new
@@ -1851,6 +1846,21 @@ static void outputModePop(ShellState *p){
memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
}
/*
** Set output mode to text or binary for Windows.
*/
static void setCrlfMode(ShellState *p){
#ifdef _WIN32
if( p->crlfMode ){
sqlite3_fsetmode(p->out, _O_TEXT);
}else{
sqlite3_fsetmode(p->out, _O_BINARY);
}
#else
UNUSED_PARAMETER(p);
#endif
}
/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
@@ -1901,9 +1911,10 @@ static const char *unused_string(
**
** See also: output_quoted_escaped_string()
*/
static void output_quoted_string(FILE *out, const char *z){
static void output_quoted_string(ShellState *p, const char *z){
int i;
char c;
FILE *out = p->out;
sqlite3_fsetmode(out, _O_BINARY);
if( z==0 ) return;
for(i=0; (c = z[i])!=0 && c!='\''; i++){}
@@ -1929,7 +1940,7 @@ static void output_quoted_string(FILE *out, const char *z){
}
sqlite3_fputs("'", out);
}
sqlite3_fsetmode(out, _O_TEXT);
setCrlfMode(p);
}
/*
@@ -1941,9 +1952,10 @@ static void output_quoted_string(FILE *out, const char *z){
** This is like output_quoted_string() but with the addition of the \r\n
** escape mechanism.
*/
static void output_quoted_escaped_string(FILE *out, const char *z){
static void output_quoted_escaped_string(ShellState *p, const char *z){
int i;
char c;
FILE *out = p->out;
sqlite3_fsetmode(out, _O_BINARY);
for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
if( c==0 ){
@@ -1996,7 +2008,7 @@ static void output_quoted_escaped_string(FILE *out, const char *z){
sqlite3_fprintf(out, ",'%s',char(10))", zNL);
}
}
sqlite3_fsetmode(stdout, _O_TEXT);
setCrlfMode(p);
}
/*
@@ -2793,7 +2805,7 @@ static int shell_callback(
}
sqlite3_fputs(p->rowSeparator, p->out);
}
sqlite3_fsetmode(p->out, _O_TEXT);
setCrlfMode(p);
break;
}
case MODE_Insert: {
@@ -2821,9 +2833,9 @@ static int shell_callback(
sqlite3_fputs("NULL", p->out);
}else if( aiType && aiType[i]==SQLITE_TEXT ){
if( ShellHasFlag(p, SHFLG_Newlines) ){
output_quoted_string(p->out, azArg[i]);
output_quoted_string(p, azArg[i]);
}else{
output_quoted_escaped_string(p->out, azArg[i]);
output_quoted_escaped_string(p, azArg[i]);
}
}else if( aiType && aiType[i]==SQLITE_INTEGER ){
sqlite3_fputs(azArg[i], p->out);
@@ -2852,9 +2864,9 @@ static int shell_callback(
}else if( isNumber(azArg[i], 0) ){
sqlite3_fputs(azArg[i], p->out);
}else if( ShellHasFlag(p, SHFLG_Newlines) ){
output_quoted_string(p->out, azArg[i]);
output_quoted_string(p, azArg[i]);
}else{
output_quoted_escaped_string(p->out, azArg[i]);
output_quoted_escaped_string(p, azArg[i]);
}
}
sqlite3_fputs(");\n", p->out);
@@ -2907,7 +2919,7 @@ static int shell_callback(
if( p->cnt==0 && p->showHeader ){
for(i=0; i<nArg; i++){
if( i>0 ) sqlite3_fputs(p->colSeparator, p->out);
output_quoted_string(p->out, azCol[i]);
output_quoted_string(p, azCol[i]);
}
sqlite3_fputs(p->rowSeparator, p->out);
}
@@ -2917,7 +2929,7 @@ static int shell_callback(
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
sqlite3_fputs("NULL", p->out);
}else if( aiType && aiType[i]==SQLITE_TEXT ){
output_quoted_string(p->out, azArg[i]);
output_quoted_string(p, azArg[i]);
}else if( aiType && aiType[i]==SQLITE_INTEGER ){
sqlite3_fputs(azArg[i], p->out);
}else if( aiType && aiType[i]==SQLITE_FLOAT ){
@@ -2932,7 +2944,7 @@ static int shell_callback(
}else if( isNumber(azArg[i], 0) ){
sqlite3_fputs(azArg[i], p->out);
}else{
output_quoted_string(p->out, azArg[i]);
output_quoted_string(p, azArg[i]);
}
}
sqlite3_fputs(p->rowSeparator, p->out);
@@ -4751,7 +4763,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
if( !dataOnly ) sqlite3_fputs("DELETE FROM sqlite_sequence;\n", p->out);
/* no-op */
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
if( !dataOnly ) sqlite3_fputs("ANALYZE sqlite_schema;\n", p->out);
}else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
@@ -4936,10 +4948,7 @@ static const char *(azHelp[]) = {
".clone NEWDB Clone data into NEWDB from the existing database",
#endif
".connection [close] [#] Open or close an auxiliary database connection",
#if defined(_WIN32) && !defined(SQLITE_U8TEXT_ONLY) \
&& !defined(SQLITE_U8TEXT_STDIO)
".crnl on|off Translate \\n to \\r\\n. Default ON",
#endif /* _WIN32 && U8TEXT_ONLY && U8TEXT_STDIO */
".crlf ?on|off? Whether or not to use \\r\\n line endings",
".databases List names and files of attached databases",
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
#if SQLITE_SHELL_HAVE_RECOVER
@@ -5938,7 +5947,7 @@ static void output_file_close(FILE *f){
** recognized and do the right thing. NULL is returned if the output
** filename is "off".
*/
static FILE *output_file_open(const char *zFile, int bTextMode){
static FILE *output_file_open(const char *zFile){
FILE *f;
if( cli_strcmp(zFile,"stdout")==0 ){
f = stdout;
@@ -5947,7 +5956,7 @@ static FILE *output_file_open(const char *zFile, int bTextMode){
}else if( cli_strcmp(zFile, "off")==0 ){
f = 0;
}else{
f = sqlite3_fopen(zFile, bTextMode ? "w" : "wb");
f = sqlite3_fopen(zFile, "w");
if( f==0 ){
sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zFile);
}
@@ -6420,6 +6429,7 @@ static void output_redir(ShellState *p, FILE *pfNew){
sqlite3_fputs("Output already redirected.\n", stderr);
}else{
p->out = pfNew;
setCrlfMode(p);
if( p->mode==MODE_Www ){
sqlite3_fputs(
"<!DOCTYPE html>\n"
@@ -6475,6 +6485,7 @@ static void output_reset(ShellState *p){
}
p->outfile[0] = 0;
p->out = stdout;
setCrlfMode(p);
}
#else
# define output_redir(SS,pfO)
@@ -8427,9 +8438,9 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
/* Undocumented. Legacy only. See "crnl" below */
/* Undocumented. Legacy only. See "crlf" below */
if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
eputz("The \".binary\" command is deprecated. Use \".crnl\" instead.\n");
eputz("The \".binary\" command is deprecated.\n");
rc = 1;
}else
@@ -8555,22 +8566,18 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='c' && n==4 && cli_strncmp(azArg[0], "crnl", n)==0 ){
#if !defined(_WIN32) || defined(SQLITE_U8TEXT_ONLY) \
|| defined(SQLITE_U8TEXT_STDIO)
sqlite3_fputs("The \".crnl\" command is disable in this build.\n", p->out);
#else
if( c=='c' && n==4
&& (cli_strncmp(azArg[0], "crlf", n)==0
|| cli_strncmp(azArg[0], "crnl",n)==0)
){
if( nArg==2 ){
if( booleanValue(azArg[1]) ){
sqlite3_fsetmode(p->out, _O_TEXT);
}else{
sqlite3_fsetmode(p->out, _O_BINARY);
}
}else{
eputz("Usage: .crnl on|off\n");
rc = 1;
}
#ifdef _WIN32
p->crlfMode = booleanValue(azArg[1]);
#else
p->crlfMode = 0;
#endif
}
sqlite3_fprintf(stderr, "crlf is %s\n", p->crlfMode ? "ON" : "OFF");
}else
if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
@@ -9650,7 +9657,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
output_file_close(p->pLog);
if( cli_strcmp(zFile,"on")==0 ) zFile = "stdout";
p->pLog = output_file_open(zFile, 0);
p->pLog = output_file_open(zFile);
}
}else
@@ -9905,7 +9912,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|| (c=='w' && n==3 && cli_strcmp(azArg[0],"www")==0)
){
char *zFile = 0;
int bTxtMode = 0;
int i;
int eMode = 0;
int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */
@@ -9987,11 +9993,9 @@ static int do_meta_command(char *zLine, ShellState *p){
/* web-browser mode. */
newTempFile(p, "html");
if( !bPlain ) p->mode = MODE_Www;
bTxtMode = 1;
}else{
/* text editor mode */
newTempFile(p, "txt");
bTxtMode = 1;
}
sqlite3_free(zFile);
zFile = sqlite3_mprintf("%s", p->zTempFile);
@@ -10015,7 +10019,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
#endif
}else{
FILE *pfFile = output_file_open(zFile, bTxtMode);
FILE *pfFile = output_file_open(zFile);
if( pfFile==0 ){
if( cli_strcmp(zFile,"off")!=0 ){
sqlite3_fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
@@ -10023,13 +10027,13 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
} else {
output_redir(p, pfFile);
if( zBom ) sqlite3_fputs(zBom, pfFile);
if( bPlain && eMode=='w' ){
sqlite3_fputs(
"<!DOCTYPE html>\n<BODY>\n<PLAINTEXT>\n",
pfFile
);
}
if( zBom ) sqlite3_fputs(zBom, pfFile);
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
}
}
@@ -10226,7 +10230,6 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifdef SQLITE_OMIT_POPEN
eputz("Error: pipes are not supported in this OS\n");
rc = 1;
p->out = stdout;
#else
p->in = sqlite3_popen(azArg[1]+1, "r");
if( p->in==0 ){
@@ -11213,7 +11216,7 @@ static int do_meta_command(char *zLine, ShellState *p){
/* Begin redirecting output to the file "testcase-out.txt" */
if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
output_reset(p);
p->out = output_file_open("testcase-out.txt", 0);
p->out = output_file_open("testcase-out.txt");
if( p->out==0 ){
eputz("Error: cannot open 'testcase-out.txt'\n");
}
@@ -11717,7 +11720,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else{
output_file_close(p->traceOut);
p->traceOut = output_file_open(z, 0);
p->traceOut = output_file_open(z);
}
}
if( p->traceOut==0 ){
@@ -12594,6 +12597,9 @@ static void main_init(ShellState *data) {
memset(data, 0, sizeof(*data));
data->normalMode = data->cMode = data->mode = MODE_List;
data->autoExplain = 1;
#ifdef _WIN32
data->crlfMode = 1;
#endif
data->pAuxDb = &data->aAuxDb[0];
memcpy(data->colSeparator,SEP_Column, 2);
memcpy(data->rowSeparator,SEP_Row, 2);
+11 -1
View File
@@ -4232,7 +4232,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** is the number of bytes in the input string <i>including</i>
** the nul-terminator.
** Note that nByte measure the length of the input in bytes, not
** characters, even for the UTF-16 inferfaces.
** characters, even for the UTF-16 interfaces.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql. These routines only
@@ -9344,6 +9344,16 @@ typedef struct sqlite3_backup sqlite3_backup;
** APIs are not strictly speaking threadsafe. If they are invoked at the
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
**
** <b>Alternatives To Using The Backup API</b>
**
** Other techniques for safely creating a consistent backup of an SQLite
** database include:
**
** <ul>
** <li> The [VACUUM INTO] command.
** <li> The [sqlite3_rsync] utility program.
** </ul>
*/
sqlite3_backup *sqlite3_backup_init(
sqlite3 *pDest, /* Destination database handle */
+1 -1
View File
@@ -3104,7 +3104,7 @@ struct Expr {
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
/* 0x80000000 // Available */
#define EP_SubtArg 0x80000000 /* Is argument to SQLITE_SUBTYPE function */
/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
+15 -1
View File
@@ -3981,7 +3981,7 @@ static int SQLITE_TCLAPI DbMain(
** The EXTERN macros are required by TCL in order to work on windows.
*/
EXTERN int Sqlite3_Init(Tcl_Interp *interp){
int rc = Tcl_InitStubs(interp, "8.4", 0) ? TCL_OK : TCL_ERROR;
int rc = Tcl_InitStubs(interp, "8.5-", 0) ? TCL_OK : TCL_ERROR;
if( rc==TCL_OK ){
Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
#ifndef SQLITE_3_SUFFIX_ONLY
@@ -4037,6 +4037,20 @@ EXTERN int sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
static const char *tclsh_main_loop(void){
static const char zMainloop[] =
"if {[llength $argv]>=1} {\n"
#ifdef WIN32
"set new [list]\n"
"foreach arg $argv {\n"
"if {[file exists $arg]} {\n"
"lappend new $arg\n"
"} else {\n"
"foreach match [lsort [glob -nocomplain $arg]] {\n"
"lappend new $match\n"
"}\n"
"}\n"
"}\n"
"set argv $new\n"
"unset new\n"
#endif
"set argv0 [lindex $argv 0]\n"
"set argv [lrange $argv 1 end]\n"
"source $argv0\n"
+1 -1
View File
@@ -136,7 +136,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
while( zIn<zTerm && (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
if( c<0x80 \
-58
View File
@@ -6302,58 +6302,6 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
}
}
/*
** Expression Node callback for sqlite3ExprCanReturnSubtype().
**
** Only a function call is able to return a subtype. So if the node
** is not a function call, return WRC_Prune immediately.
**
** A function call is able to return a subtype if it has the
** SQLITE_RESULT_SUBTYPE property.
**
** Assume that every function is able to pass-through a subtype from
** one of its argument (using sqlite3_result_value()). Most functions
** are not this way, but we don't have a mechanism to distinguish those
** that are from those that are not, so assume they all work this way.
** That means that if one of its arguments is another function and that
** other function is able to return a subtype, then this function is
** able to return a subtype.
*/
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
int n;
FuncDef *pDef;
sqlite3 *db;
if( pExpr->op!=TK_FUNCTION ){
return WRC_Prune;
}
assert( ExprUseXList(pExpr) );
db = pWalker->pParse->db;
n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
pWalker->eCode = 1;
return WRC_Prune;
}
return WRC_Continue;
}
/*
** Return TRUE if expression pExpr is able to return a subtype.
**
** A TRUE return does not guarantee that a subtype will be returned.
** It only indicates that a subtype return is possible. False positives
** are acceptable as they only disable an optimization. False negatives,
** on the other hand, can lead to incorrect answers.
*/
static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = pParse;
w.xExprCallback = exprNodeCanReturnSubtype;
sqlite3WalkExpr(&w, pExpr);
return w.eCode;
}
/*
** The index pIdx is used by a query and contains one or more expressions.
** In other words pIdx is an index on an expression. iIdxCur is the cursor
@@ -6387,12 +6335,6 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
continue;
}
if( sqlite3ExprIsConstant(0,pExpr) ) continue;
if( pExpr->op==TK_FUNCTION && sqlite3ExprCanReturnSubtype(pParse,pExpr) ){
/* Functions that might set a subtype should not be replaced by the
** value taken from an expression index since the index omits the
** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */
continue;
}
p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
if( p==0 ) break;
p->pIENext = pParse->pIdxEpr;
+16 -11
View File
@@ -219,20 +219,25 @@ static int isLikeOrGlob(
z = (u8*)pRight->u.zToken;
}
if( z ){
/* Count the number of prefix characters prior to the first wildcard.
** If the underlying database has a UTF16LE encoding, then only consider
** ASCII characters. Note that the encoding of z[] is UTF8 - we are
** dealing with only UTF8 here in this code, but the database engine
** itself might be processing content using a different encoding. */
/* Count the number of prefix bytes prior to the first wildcard.
** or U+fffd character. If the underlying database has a UTF16LE
** encoding, then only consider ASCII characters. Note that the
** encoding of z[] is UTF8 - we are dealing with only UTF8 here in
** this code, but the database engine itself might be processing
** content using a different encoding. */
cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
if( c==wc[3] && z[cnt]!=0 ){
if( c==wc[3] && z[cnt]>0 && z[cnt]<0x80 ){
cnt++;
}else if( c>=0x80 && ENC(db)==SQLITE_UTF16LE ){
cnt--;
break;
}else if( c>=0x80 ){
const u8 *z2 = z+cnt-1;
if( sqlite3Utf8Read(&z2)==0xfffd || ENC(db)==SQLITE_UTF16LE ){
cnt--;
break;
}else{
cnt = (int)(z2-z);
}
}
}
@@ -244,7 +249,7 @@ static int isLikeOrGlob(
** range search. The third is because the caller assumes that the pattern
** consists of at least one character after all escapes have been
** removed. */
if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && 255!=(u8)z[cnt-1] ){
if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && ALWAYS(255!=(u8)z[cnt-1]) ){
Expr *pPrefix;
/* A "complete" match if the pattern ends with "*" or "%" */
+27
View File
@@ -276,4 +276,31 @@ do_catchsql_test 6.3 {
UPDATE t1 SET x='hello world' WHERE rowid=1;
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 7.0 {
BEGIN;
CREATE TABLE p1(x PRIMARY KEY);
CREATE TABLE c1(y);
PRAGMA schema_version = 0;
PRAGMA writable_schema = RESET;
INSERT INTO c1 VALUES(1000);
ROLLBACK;
}
do_execsql_test 7.1 {
PRAGMA table_info = p1;
} {0 x {} 0 {} 1}
do_catchsql_test 7.2 {
SELECT * FROM p1;
} {1 {database disk image is malformed}}
do_catchsql_test 7.3 {
PRAGMA integrity_check
} {1 {database disk image is malformed}}
finish_test
+83
View File
@@ -0,0 +1,83 @@
# 2024-10-05
#
# 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 implements regression tests for SQLite library. The
# focus of this file is testing indexes on expressions.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix indexexpr3
do_execsql_test 1.0 {
CREATE TABLE t1(a, j);
INSERT INTO t1 VALUES(1, '{x:"one"}');
INSERT INTO t1 VALUES(2, '{x:"two"}');
INSERT INTO t1 VALUES(3, '{x:"three"}');
CREATE INDEX i1 ON t1( json_extract(j, '$.x') );
CREATE INDEX i2 ON t1( a, json_extract(j, '$.x') );
}
proc do_hasfunction_test {tn sql res} {
set nFunction 0
db eval "EXPLAIN $sql" x {
if {$x(opcode)=="Function"} {
incr nFunction
}
}
do_execsql_test $tn "
SELECT $nFunction;
$sql
" $res
}
do_hasfunction_test 1.1 {
SELECT json_extract(j, '$.x') FROM t1 ORDER BY 1;
} {
0 one three two
}
do_hasfunction_test 1.2 {
SELECT json_extract(j, '$.x') FROM t1 WHERE a=2
} {
0 two
}
do_hasfunction_test 1.3 {
SELECT coalesce(json_extract(j, '$.x'), 'five') FROM t1 WHERE a=2
} {
0 two
}
do_hasfunction_test 1.4 {
SELECT json_extract(j, '$.x') || '.two' FROM t1 WHERE a=2
} {
0 two.two
}
do_hasfunction_test 1.5 {
SELECT json_insert( '{}', '$.y', json_extract(j, '$.x') ) FROM t1 WHERE a=2
} {
2 {{"y":"two"}}
}
do_hasfunction_test 1.6 {
SELECT json_insert( '{}', '$.y', coalesce( json_extract(j, '$.x'), 'five' ) )
FROM t1 WHERE a=2
} {
2 {{"y":"two"}}
}
finish_test
+3 -3
View File
@@ -731,16 +731,16 @@ ifcapable like_opt&&!icu {
}
do_test like-9.5.1 {
set res [sqlite3_exec_hex db {
SELECT x FROM t2 WHERE x LIKE '%fe%25'
SELECT 1 FROM t2 WHERE x LIKE '%fe%25'
}]
} {0 {}}
} {0 {1 1}}
ifcapable explain {
do_test like-9.5.2 {
set res [sqlite3_exec_hex db {
EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%fe%25'
}]
regexp {INDEX i2} $res
} {1}
} {0}
}
# Do an SQL statement. Append the search count to the end of the result.
+48
View File
@@ -146,6 +146,54 @@ do_test lock5-flock.8 {
db2 close
} {}
do_test lock5-flock.9 {
sqlite3 db test.db -vfs unix-flock
execsql {
SELECT * FROM t1
}
} {1 2}
do_test lock5-flock.10 {
sqlite3 db2 test.db -vfs unix-flock
execsql {
SELECT * FROM t1
} db2
} {1 2}
do_test lock5-flock.10 {
execsql {
PRAGMA cache_size = 1;
BEGIN;
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
)
INSERT INTO t1 SELECT i, i+1 FROM s;
}
catchsql {
SELECT * FROM t1
} db2
} {1 {database is locked}}
if {[permutation]!="inmemory_journal"} {
do_test lock5-flock.11 {
forcecopy test.db test.db2
forcecopy test.db-journal test.db2-journal
db2 close
sqlite3 db2 test.db2 -vfs unix-flock
catchsql {
SELECT * FROM t1
} db2
} {0 {1 2}}
do_test lock5-flock.12 {
file exists test.db2-journal
} 0
}
db close
db2 close
}
#####################################################################
+4 -1
View File
@@ -1063,7 +1063,10 @@ do_test shell1-5.0 {
continue
}
# Tcl 8.7 maps 0x80 through 0x9f into valid UTF8. So skip those tests.
if {$i>=0x80 && ($i<=0x9F || $tcl_version>=9.0)} continue
if {$i>=0x80} {
if {$i<=0x9F || $tcl_version>=9.0} continue
if {$tcl_platform(platform)=="windows"} continue
}
if {$i>=0xE0 && $tcl_platform(os)=="OpenBSD"} continue
if {$i>=0xE0 && $i<=0xEF && $tcl_platform(os)=="Linux"} continue
set hex [format %02X $i]
+1 -2
View File
@@ -95,7 +95,7 @@ proc run_thread_tests {{print_warning 0}} {
if {[info commands sqlthread] eq ""} {
set zProblem "SQLite build is not threadsafe"
}
if {![info exists ::tcl_platform(threaded)]} {
if {![tcl::pkgconfig get threaded]} {
set zProblem "Linked against a non-threadsafe Tcl build"
}
if {[info exists zProblem]} {
@@ -107,4 +107,3 @@ proc run_thread_tests {{print_warning 0}} {
}
return 0
+4 -13
View File
@@ -54,16 +54,7 @@ close $in
scan $vers %d.%d.%d v1 v2 v3
set v2 [format 3%02d%02d00 $v2 $v3]
set name sqlite-tools-$OS-$ARCH-$v2.zip
if {$OS=="win32"} {
# The win32 tar.exe supports the -a ("auto-compress") option. This causes
# tar to create an archive type based on the extension of the output file.
# In this case, a zip file.
puts "tar -a -cf $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE"
puts [exec tar -a -cf $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE]
puts "$name: [file size $name] bytes"
} else {
puts "zip $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE"
puts [exec zip $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE]
puts [exec ls -l $name]
}
set toollist "sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE sqlite3_rsync$EXE"
puts "zip $name {*}$toollist"
exec zip $name {*}$toollist
puts "$name: [file size $name] bytes"
+10 -7
View File
@@ -21,7 +21,7 @@
#include "sqlite3.h"
static const char zUsage[] =
"sqlite3-rsync ORIGIN REPLICA ?OPTIONS?\n"
"sqlite3_rsync ORIGIN REPLICA ?OPTIONS?\n"
"\n"
"One of ORIGIN or REPLICA is a pathname to a database on the local\n"
"machine and the other is of the form \"USER@HOST:PATH\" describing\n"
@@ -30,7 +30,7 @@ static const char zUsage[] =
"\n"
"OPTIONS:\n"
"\n"
" --exe PATH Name of the sqlite3-rsync program on the remote side\n"
" --exe PATH Name of the sqlite3_rsync program on the remote side\n"
" --help Show this help screen\n"
" --ssh PATH Name of the SSH program used to reach the remote side\n"
" -v Verbose. Multiple v's for increasing output\n"
@@ -1197,6 +1197,7 @@ static void originSide(SQLiteRsync *p){
int c = 0;
unsigned int nPage = 0;
unsigned int iPage = 0;
unsigned int lockBytePage = 0;
unsigned int szPg = 0;
sqlite3_stmt *pCkHash = 0;
char buf[200];
@@ -1235,6 +1236,7 @@ static void originSide(SQLiteRsync *p){
p->nPage = nPage;
p->szPage = szPg;
p->iProtocol = PROTOCOL_VERSION;
lockBytePage = (1<<30)/szPg + 1;
}
}
@@ -1290,6 +1292,7 @@ static void originSide(SQLiteRsync *p){
" INSERT INTO badHash SELECT n FROM c",
iPage+1, p->nPage);
}
runSql(p, "DELETE FROM badHash WHERE pgno=%d", lockBytePage);
pStmt = prepareStmt(p,
"SELECT pgno, data"
" FROM badHash JOIN sqlite_dbpage('main') USING(pgno)");
@@ -1583,13 +1586,13 @@ static char *hostSeparator(const char *zIn){
**
** Input formats:
**
** (1) sqlite3-rsync FILENAME1 USER@HOST:FILENAME2
** (1) sqlite3_rsync FILENAME1 USER@HOST:FILENAME2
**
** (2) sqlite3-rsync USER@HOST:FILENAME1 FILENAME2
** (2) sqlite3_rsync USER@HOST:FILENAME1 FILENAME2
**
** (3) sqlite3-rsync --origin FILENAME1
** (3) sqlite3_rsync --origin FILENAME1
**
** (4) sqlite3-rsync --replica FILENAME2
** (4) sqlite3_rsync --replica FILENAME2
**
** The user types (1) or (2). SSH launches (3) or (4).
**
@@ -1613,7 +1616,7 @@ int main(int argc, char const * const *argv){
FILE *pOut = 0;
int childPid = 0;
const char *zSsh = "ssh";
const char *zExe = "sqlite3-rsync";
const char *zExe = "sqlite3_rsync";
char *zCmd = 0;
sqlite3_int64 tmStart;
sqlite3_int64 tmEnd;
+4
View File
@@ -854,12 +854,16 @@ int main(int argc, char **argv){
xErr = errorMsgNH;
continue;
}
usage:
fprintf(stderr, "Usage: %s DIRECTORY\n"
" or: %s --sha1 FILE ...\n"
" or: %s --sha3 FILE ...\n",
argv[0], argv[0], argv[0]);
return 1;
}
if( !zDir ){
goto usage;
}
if( strlen(zDir)>1000 ){
fprintf(stderr, "Directory argument too big: [%s]\n", zDir);
return 1;