Compare commits

..

49 Commits

Author SHA1 Message Date
drh 2f82acc036 Fix minor OOM problems.
FossilOrigin-Name: 8b23d80271aab38abe42ee8b3ca4b746572ecef26c2a37b094b01560e6be9d45
2020-06-07 22:44:23 +00:00
drh bf7909734a AggInfo objects might be referenced even after the sqlite3Select() function
that created them has exited.  So AggInfo cannot be a stack variable.  And it
must not be freed until the Parse object is destroyed.

FossilOrigin-Name: 3c840b4df306e2db1da08673e9ede973b4cb6d2b3f9eeeab5835e39452ee3056
2020-06-07 20:18:07 +00:00
drh 896366282d Alternative fix to ticket [c8d3b9f0a750a529]: Prior to deleting or modifying
an Expr not that is referenced by an AggInfo, modify the AggInfo to get its
own copy of the original Expr.

FossilOrigin-Name: 7682d8a768fbccfe0cc956e9f6481637146e1ab9763b248ff11052761ce32e32
2020-06-07 17:33:18 +00:00
drh a0365c487c In the debugging treeview output, change the name of "SELECT-expr" expression
nodes to be "subquery-expr", so as to not confuse them with actual SELECT
nodes.

FossilOrigin-Name: c1c8937a30feff6aa4385b0c264fd8e70d54422a0629c2ce38082d85d3334a57
2020-06-05 04:01:50 +00:00
drh c060508445 Always use ?...? to indicate optional arguments in the output of ".help"
in the CLI.  Change ".mode column" so that it automatically activates
".headers on" if headers have not been previously turned on or off.

FossilOrigin-Name: 2827c0a186596299e43eb3e7378eea462d2b060b2c3388ce5cb2bc8e0b43999e
2020-06-05 00:54:27 +00:00
drh 0908e38536 Add support for "box" mode in the CLI: Like "table" except that it uses
unicode box-drawing characters instead of ascii-art.

FossilOrigin-Name: 6da784c9e174744d6deeb76c553b515b96c1fcb80c55a281e476959ec680fb72
2020-06-04 18:05:39 +00:00
drh 634af38115 Improved display of ".mode table" output for empty result sets.
FossilOrigin-Name: 7efabd683b79743b407ad71dda56db00fb0d668828bdc342145816b4f1c3bf3a
2020-06-04 16:54:10 +00:00
dan b55389412f Use __has_extension(c_atomic) instead of __has_feature(c_atomic) to detect support for atomic load and store operations with clang.
FossilOrigin-Name: 362255791f8801e0d9869e36239b8b2cb29c38bf0b86894bd2d159ce46d8447e
2020-06-04 16:34:49 +00:00
dan ec206a7d34 Use AtomicStore() to set values in the wal-index hash table.
FossilOrigin-Name: 1ab30c75f2fe14d1ee77d0eace4e29ba8f805d63e2da0897b111ea1311f409aa
2020-06-04 16:07:51 +00:00
drh 21b473de78 Work around a bug in clang-11.0.0.
FossilOrigin-Name: 3c2bf8042ec46195c67dfd91df084f5bc19162fd26389920e716b310c80deea6
2020-06-04 02:50:47 +00:00
drh a5f3fb3015 Fix for ticket [810dc8038872e212]. Thank to user "Maxulite" for tracking
down the problem!

FossilOrigin-Name: 89af93d77fa7959a4ee7364bae6c02c40963a3cdf80b0a4a8af9c9764d5c7bb5
2020-06-03 19:28:10 +00:00
drh 56f1873d10 Simplification to the interrupt handling logic in sqlite3VdbeExec() saves
a few bytes of code space.

FossilOrigin-Name: 43e0e59bd4e34c6e88c004ea951c0d76ff1cf0a034389f490495a5d12e239382
2020-06-03 15:59:22 +00:00
drh 094afffaec Improve the query planner so that it is better able to find full
index scan plan when there is an INDEXED BY clause.

FossilOrigin-Name: d901837fea1ed54de43ad59eb47c02cbfd2eb215fc57317b5ea8c22a7df947c4
2020-06-03 03:00:09 +00:00
drh e566cebb26 Draw the dashes below the headers in "explain" mode in the CLI.
FossilOrigin-Name: c6b7833ac7d9cc75cb45d5e8041367ebd6f197f776766e6143535c227fc72a20
2020-05-30 15:34:49 +00:00
drh e557b0155b Improved VDBE comments on the ANALYZE code generator. This change
also fixes a harmless use of an uninitialized integer variable as an input
to the %d format on a VDBE comment.

FossilOrigin-Name: 1cb248a3fc4c35c5bc3993b554edcccaa5c5e91570af67ebb99643a15221ae33
2020-05-30 00:30:08 +00:00
mistachkin 375b0b014b Enhancements to the incremental build support for MSVC.
FossilOrigin-Name: 2e25d915bcb8d6f1747f9befdef64d2e0e495cc6c5948a8eff5d0097b6613d06
2020-05-29 21:06:52 +00:00
drh 42c2a04eb7 Remove a stray "&" character in the CLI, detected by a clang warning.
FossilOrigin-Name: 5865d2f2d0333024366ecf1d919535fd4ec05c637feff16d75028ccdc8db4b50
2020-05-29 20:16:19 +00:00
drh 02c17a4da7 Add the "shelltest" target to the MSVC makefile as well.
FossilOrigin-Name: 9924c0456bfcd2058c9620a93dfbfd4c7d960c68910ce6aed7364dff42baba5c
2020-05-29 19:45:03 +00:00
drh 9776784f94 Fix the ".import" command of the CLI to clean up better after errors.
Add the new "shelltest" makefile target on unix platforms.

FossilOrigin-Name: 50d4ddf1330b88551de51439eb535f385dee6b53013802dd62f832d16b3025b6
2020-05-29 19:39:35 +00:00
drh 7da29a3ad3 Improvements to help text for the CLI.
FossilOrigin-Name: 6a01e4c444b072e31a320121a6810d7c986c2c54ce45f9b11683233b1e7af8da
2020-05-29 19:17:20 +00:00
drh 1d29fd85a3 Fix a memory leak in the CLI when an unknown or unrecognized
argument is given to the ".dump" command.

FossilOrigin-Name: 71bfbbcc1a8d0e02073a381a5b31a5ccd5477011b22904b9989b6129d81f02e7
2020-05-29 19:03:03 +00:00
drh 8c748633a9 Improvements to columnar output in the CLI. Columns automatically expand
to contain the largest row.

FossilOrigin-Name: 4e1db8e9a9ee370a398f13fd8546a520111b8cfb84460389535b5bc5bd9f4f82
2020-05-29 16:15:58 +00:00
drh 0285d98de7 Space to hold the ".width" of columns in the CLI is now obtained from
malloc() and hence is not limited in the number of columns supported.

FossilOrigin-Name: 445ed5dab2c26e9f4a7fb5277abdba3359d23cf5318cfd0d8322162d9616ee7a
2020-05-29 14:38:43 +00:00
drh d6f252490e Incremental improvements to tabular output modes in the CLI. The
"markdown" and "table" modes no have headers turned on by default.

FossilOrigin-Name: af28bff91ad7e2d69db0052323c9c05c75a41d4134974bd1305f1c4f579d3558
2020-05-29 12:31:53 +00:00
dan d31fcd4751 Expand upon a comment in os_unix.c. No changes to code.
FossilOrigin-Name: 77933dc4dbe0e0af3b13a14293a8bd684edc5056f4ae9291c6f95d4433bf90ce
2020-05-29 11:07:20 +00:00
drh 69c093da98 In the json output mode of the CLI, do correct quoting of escape characters.
Also, show BLOBs as JSON strings, possibly with embedded \u0000 bytes.

FossilOrigin-Name: 0278147a7d2b50bed9f59ed3d3a04ecc6d46f072eb510e463f6707df1d829020
2020-05-29 00:21:43 +00:00
drh 30c54a01db Progress toward adding new output modes to the CLI: json, table, and
markdown.

FossilOrigin-Name: 14f55fafec11491e87e6526c72cf85c689d74ba18418a1ae9646586ec206767a
2020-05-28 23:49:50 +00:00
drh c683573fd4 Enhance the ".quote" mode in the shell so that it honors .separator.
FossilOrigin-Name: b5e33ed537e7d7dcabc9f6dc91d6838e0d1657f323440e09e2e24ffa2ba6141a
2020-05-28 20:37:17 +00:00
drh 56c65c92cb When the sqlite_stat1 data is missing for some indexes of a table but is
present for the table itself or for other indexes in the same table, then do
not let the estimated number of rows in that table get too small, as
doing so can deceive the query planner into ignoring a perfectly good index.

FossilOrigin-Name: 98d4262018a81a9a36dd8beb4b02ff0e75cdcbb8a121d143157ffb37b228d60d
2020-05-28 00:45:16 +00:00
drh b639a2094a Small performance improvement and size reduction in the expression
code generator.

FossilOrigin-Name: eeb53e219551d8a05a87f1de9a7cd9af295d08a296f1f435a8509ea1252ccdcc
2020-05-27 12:44:28 +00:00
drh 399062cccb Change a datatype from i16 to int to appease Converity and help eliminate
a false-positive.

FossilOrigin-Name: 5b560ec49041d89c87ea3315d8fc17f7fb0e03a82091934be7373b290183f82e
2020-05-27 00:02:07 +00:00
drh a3d6b8e5a7 Fix the cksumvfs extension so that it will not register itself more than
once.

FossilOrigin-Name: d5cdd57150db914b61b8b9c61c6caac9690fe7b647ee2c003e75b9b62be62752
2020-05-26 20:33:18 +00:00
drh ed505ce3e4 Performance optimization in the transfer of error messages from statements
to connections.

FossilOrigin-Name: 0e898f4fed1c851cb90f940175110e632a20668a285d39f5f94f7358c3064882
2020-05-26 20:31:17 +00:00
drh 47937cfd8d Increase the version number to 3.33.0 to begin the next release cycle.
FossilOrigin-Name: 790badb390d59062cd2d8d1dec76cc6104c9425610a67503f6be38076b6a458e
2020-05-26 11:23:48 +00:00
drh ed1e910448 Changes to sqlite3SelectNew() to work around a false-positive warning
from GCC-10.  The code is very slightly larger and slower as a result.

FossilOrigin-Name: 04e1edd8e5821a377407263829ed0d87968c708c9aeb1282107ea6f39a11c1cc
2020-05-26 11:10:25 +00:00
drh bdd4f7d91c Innocuous changes to help Coverity avoid false-positives.
FossilOrigin-Name: 4ec8a5a203f10d228d0b3389120638766cc343179dbe38d5dbf69b650765934c
2020-05-26 10:54:46 +00:00
drh d63c76fb31 Version 3.32.1
FossilOrigin-Name: 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350
2020-05-25 16:19:56 +00:00
drh b6907e2993 Extra assert() statements in the printf() logic.
FossilOrigin-Name: b1b182be2ab34cec1d94c5570bc361331a34f727eb9fa4aadfabb7f1ef79f83e
2020-05-25 15:41:03 +00:00
drh 0934d64045 Defensive code that tries to prevent a recurrence of problems like the
one described in ticket [7a5279a25c57adf1]

FossilOrigin-Name: 572105de1d44bca4f18c99d373458889163611384eebbc9659474874ee1701f4
2020-05-25 15:19:52 +00:00
drh efc752b131 Fix minor compile issues with optional extensions.
FossilOrigin-Name: 3261ee9ec26bbeaa64190c12556a1d8146270b6660c70004830bd38c1b5b63f4
2020-05-25 12:49:58 +00:00
drh 91960aa53f Make sure variable declarations are at start of scope even when
SQLITE_ENABLE_SNAPSHOT is used.

FossilOrigin-Name: a77ceaf6ba934b1d73c90b8980191a65d02ad6ce1e11e6baf573b3a132685545
2020-05-25 12:02:12 +00:00
drh d3bf766127 Attempt to work around a false-positive warning in the CGo compiler.
FossilOrigin-Name: d4bf60f464789935dc193ea99bf730c8fade448c7dca13eb3ce297965980f36e
2020-05-25 01:31:09 +00:00
drh e859e43bb8 Version number to 3.32.1.
FossilOrigin-Name: 56e5063c326ffbfd3e3cb6f2b05718412aca2cb183274bfe11f5666effdd04b9
2020-05-24 12:36:20 +00:00
drh c37577bb2d When rewriting a query for window functions, if the rewrite changes the
depth of TK_AGG_FUNCTION nodes, be sure to adjust the Expr.op2 field
appropriately.  Fix for ticket [7a5279a25c57adf1]

FossilOrigin-Name: ad7bb70af9bb68d192137188bb2528f1e9e43ad164c925174ca1dafc9e1f5339
2020-05-24 03:38:37 +00:00
drh e40cc16b47 Move some utility Walker callbacks into the walker.c source file, as they
seem to belong there better.

FossilOrigin-Name: dac438236f7c5419d4e7e094e8b3f19f83cd3b1a18bc8acb14aee90d4514fa3c
2020-05-24 03:01:36 +00:00
drh ca74fbf6f1 Improvements to parse-tree tracing logic. No changes in deliverable code.
FossilOrigin-Name: f7e5a68a7ebbb97a5beb050a75b3b4cf2fd6adc54653da993a8950fb3a5799f7
2020-05-24 02:05:04 +00:00
drh 16dc07f756 Minor fix to a comment. No code changes.
FossilOrigin-Name: efdbb2b499bda8ffcfe54f5d6ece08a2c58fe7a490d9550785d806bd404abb8c
2020-05-24 00:30:38 +00:00
drh dd6c33d372 Limit the "precision" of floating-point to text conversions in the printf()
function to 100,000,000.  Fix for ticket [23439ea582241138].

FossilOrigin-Name: d08d3405878d394e08e5d3af281246edfbd81ca74cc8d16458808591512fb93d
2020-05-23 19:58:07 +00:00
drh 8e50d65aaf Improved bytecode comment.
FossilOrigin-Name: 9224f1543b51a674ad6d7db8e90d97e1b0d1abe68bed3417820ebd09d27270f9
2020-05-23 17:56:49 +00:00
38 changed files with 1107 additions and 341 deletions
+3
View File
@@ -1286,6 +1286,9 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
shelltest: $(TESTPROGS)
./testfixture$(TEXT) $(TOP)/test/permutations.test shell
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
+23 -9
View File
@@ -1495,7 +1495,7 @@ SRC12 =
# All source code files.
#
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11) $(SRC12)
# Source code to the test files.
#
@@ -1846,15 +1846,16 @@ mptest: mptester.exe
for %i in ($(SRC11)) do copy /Y %i tsrc
for %i in ($(SRC12)) do copy /Y %i tsrc
copy /Y fts5.c tsrc
copy /B tsrc\fts5.c +,,
copy /Y fts5.h tsrc
copy /B tsrc\fts5.h +,,
del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
move vdbe.new tsrc\vdbe.c
echo > .target_source
sqlite3.c: .target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
sqlite3.c: .target_source sqlite3ext.h sqlite3session.h $(MKSQLITE3C_TOOL)
$(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
copy $(TOP)\ext\session\sqlite3session.h .
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
@@ -1869,7 +1870,8 @@ sqlite3.lo: $(SQLITE3C)
# Rules to build the LEMON compiler generator
#
lempar.c: $(TOP)\tool\lempar.c
copy $(TOP)\tool\lempar.c .
copy /Y $(TOP)\tool\lempar.c .
copy /B lempar.c +,,
lemon.exe: $(TOP)\tool\lemon.c lempar.c
$(BCC) $(NO_WARN) -Daccess=_access \
@@ -2169,7 +2171,8 @@ parse.h: parse.c
parse.c: $(TOP)\src\parse.y lemon.exe
del /Q parse.y parse.h parse.h.temp 2>NUL
copy $(TOP)\src\parse.y .
copy /Y $(TOP)\src\parse.y .
copy /B parse.y +,,
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S parse.y
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
@@ -2182,8 +2185,13 @@ sqlite3ext.h: .target_source
copy /Y sqlite3ext.h tsrc\sqlite3ext.h
!ELSE
copy /Y tsrc\sqlite3ext.h sqlite3ext.h
copy /B sqlite3ext.h +,,
!ENDIF
sqlite3session.h: $(TOP)\ext\session\sqlite3session.h
copy /Y $(TOP)\ext\session\sqlite3session.h .
copy /B sqlite3session.h +,,
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \
$(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
@@ -2198,7 +2206,7 @@ SHELL_SRC = \
$(TOP)\ext\misc\shathree.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\completion.c \
$(TOP)\ext\misc\uint.c \
$(TOP)\ext\misc\uint.c \
$(TOP)\ext\expert\sqlite3expert.c \
$(TOP)\ext\expert\sqlite3expert.h \
$(TOP)\ext\misc\memtrace.c \
@@ -2329,7 +2337,8 @@ LSM1_SRC = \
$(TOP)\ext\lsm1\lsm_win32.c
fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
copy $(TOP)\ext\fts5\fts5parse.y .
copy /Y $(TOP)\ext\fts5\fts5parse.y .
copy /B fts5parse.y +,,
del /Q fts5parse.h 2>NUL
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S fts5parse.y
@@ -2337,11 +2346,13 @@ fts5parse.h: fts5parse.c
fts5.c: $(FTS5_SRC)
$(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl
copy $(TOP)\ext\fts5\fts5.h .
copy /Y $(TOP)\ext\fts5\fts5.h .
copy /B fts5.h +,,
lsm1.c: $(LSM1_SRC)
$(TCLSH_CMD) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
copy $(TOP)\ext\lsm1\lsm.h .
copy /Y $(TOP)\ext\lsm1\lsm.h .
copy /B lsm.h +,,
fts5.lo: fts5.c $(HDR) $(EXTHDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c
@@ -2452,6 +2463,9 @@ smoketest: $(TESTPROGS)
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
shelltest: $(TESTPROGS)
.\testfixture.exe $(TOP)\test\permutations.test shell
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
+1 -1
View File
@@ -1 +1 @@
3.32.0
3.33.0
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.32.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.33.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.32.0'
PACKAGE_STRING='sqlite 3.32.0'
PACKAGE_VERSION='3.33.0'
PACKAGE_STRING='sqlite 3.33.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1467,7 +1467,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.32.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.33.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1532,7 +1532,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.32.0:";;
short | recursive ) echo "Configuration of sqlite 3.33.0:";;
esac
cat <<\_ACEOF
@@ -1659,7 +1659,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.32.0
sqlite configure 3.33.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2078,7 +2078,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.32.0, which was
It was created by sqlite $as_me 3.33.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12243,7 +12243,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.32.0, which was
This file was extended by sqlite $as_me 3.33.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12309,7 +12309,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.32.0
sqlite config.status 3.33.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+1 -1
View File
@@ -743,7 +743,7 @@ static int cksmRegisterFunc(
static int cksmRegisterVfs(void){
int rc = SQLITE_OK;
sqlite3_vfs *pOrig;
if( sqlite3_vfs_find("cksum")!=0 ) return SQLITE_OK;
if( sqlite3_vfs_find("cksmvfs")!=0 ) return SQLITE_OK;
pOrig = sqlite3_vfs_find(0);
cksm_vfs.iVersion = pOrig->iVersion;
cksm_vfs.pAppData = pOrig;
+1
View File
@@ -17,6 +17,7 @@
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <zlib.h>
#include <assert.h>
/*
** Implementation of the "sqlar_compress(X)" SQL function.
+1 -1
View File
@@ -811,7 +811,7 @@ int sqlite3_vfsstat_init(
if( rc==SQLITE_OK ){
rc = vstatRegister(db, pzErrMsg, pApi);
if( rc==SQLITE_OK ){
rc = sqlite3_auto_extension(vstatRegister);
rc = sqlite3_auto_extension((void(*)(void))vstatRegister);
}
}
if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
+3
View File
@@ -975,6 +975,9 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
smoketest: $(TESTPROGS) fuzzcheck$(EXE)
./testfixture$(EXE) $(TOP)/test/main.test $(TESTOPTS)
shelltest: $(TESTPROGS)
./testfixture$(EXT) $(TOP)/test/permutations.test shell
# The next two rules are used to support the "threadtest" target. Building
# threadtest runs a few thread-safety tests that are implemented in C. This
# target is invoked by the releasetest.tcl script.
+41 -44
View File
@@ -1,13 +1,13 @@
C Version\s3.32.0
D 2020-05-22T17:46:16.912
C Fix\sminor\sOOM\sproblems.
D 2020-06-07T22:44:23.371
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 376f53999defeb32b7ad2626fd58aae8f3694c38ab7ee30c2289e0d0525a9238
F Makefile.in 8d79d12bae1b624d32cf9a698ecc797bfa908ab7eabac5d76faf130c4d362223
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
F Makefile.msc 8d00aeba2609bb498dded5eead2890126321f02e292573bf29bf2d18487d37bd
F Makefile.msc 08268b28e97fce2475c4a9bd7ba84a99827d6cf9e6b46952409821f6a12ee46d
F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
F VERSION 980d78a2ce04a1fd0ebefbaabd665f7f9186563820629ee29c6e350e96f19b52
F VERSION 5db2ee2cfcc790af73775fa485c13b2e8ccaa5936c6e1f47aedeba7056041ca5
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -34,7 +34,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
F configure 4bbb5f13998f2faf929b9ae708aea9fbcb08a46cb6dd3150e36c3f09c0a05a75 x
F configure 5a2d453f527dcf969eecaac335d8261b3f1a8a6bd2c693a00dd7d18c29ccc7e4 x
F configure.ac 798a24cee2879325ca5b688a618199eb32cc77ed8136edbaa43d9137b470d54e
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
@@ -285,7 +285,7 @@ F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
F ext/misc/btreeinfo.c 26004b7a6be320ec08fc20ca8d0f01fccb00a98cbe0f3197446794ff2a506aa3
F ext/misc/carray.c 91e9a7f512fda934894bed30464552fffa7d3073b5be04189ae0bd0c59f26bfd
F ext/misc/cksumvfs.c b0d07f2e1bb08f8b6f311f4e454360b6a7f0021912c326428d74900020f29c31
F ext/misc/cksumvfs.c a3271f5cc3f87d80897cca76d54220380aeae3448efd23fefe47853443ef1185
F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
F ext/misc/completion.c a0efe03edfdc4f717c61e6c9b0bfe2708ff7878010dae3174980a68fdf76aabc
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
@@ -317,7 +317,7 @@ F ext/misc/sha1.c c8f2253c8792ffab9517695ea7d88c079f0395a5505eefef5c8198fe184ed5
F ext/misc/shathree.c 135b7c145db4a09b1650c3e7aff9cb538763a9a361e834c015dd1aaf8d5c9a00
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
F ext/misc/sqlar.c c9e5d58544e1506135806a1e0f525f92d4bb6bb125348dce469d778fb334fbce
F ext/misc/sqlar.c 0ace5d3c10fe736dc584bf1159a36b8e2e60fab309d310cd8a0eecd9036621b6
F ext/misc/stmt.c 35063044a388ead95557e4b84b89c1b93accc2f1c6ddea3f9710e8486a7af94a
F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
F ext/misc/totype.c fa4aedeb07f66169005dffa8de3b0a2b621779fd44f85c103228a42afa71853b
@@ -326,7 +326,7 @@ F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061e
F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
F ext/misc/vfslog.c 3b25c2f56ba60788db247287be6ab024b53c4afffd412b4876db563389be0d35
F ext/misc/vfsstat.c 77b5b4235c9f7f11eddf82487c0a422944ac2f132dafd5af3be7a68a057b1cdb
F ext/misc/vfsstat.c 389ea13983d3af926504c314f06a83cc858d5adc24b40af74aaed1fece00c118
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 520f34c3099e5b7d546f13708607dc2fa173c46b68952eecf0d19cd675fec85e
@@ -455,7 +455,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk addd0a300e90ad090dc4a934df8a6f1b6c52c057a1aebb93682aed29fb68a345
F main.mk 980ad4201300ca43e9db0f972c5f38776d1e78022252bf3a8c0fec7ddda540df
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -468,7 +468,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 826bc4561456094cf758f095776026f25892a2bb3a7cd86742323267dc9bdb5f
F src/analyze.c 953a6c43870ccaf080597244e1eeb4dc2ff6cb84f9501b24e46323de36970b61
F src/analyze.c 2c77bcbb8651ccced4a8cdaf8d997663813b2967787070fa26d0360de2ee4367
F src/attach.c ff2daea0fe62080192e3f262670e4f61f5a86c1e7bea9cec34e960fe79852aa1
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
F src/backup.c b1c90cd4110248c8e1273ff4578d3a84c0c34725e1b96dacd4a6294a908702de
@@ -477,7 +477,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c f14e415fcfd0b52b4e4ebd193ba5fadac5e8252c30f023389af682813af44025
F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a
F src/btreeInt.h 5c8b8749805787313ecf49eb5be3ced1e94bbf8ef54bb01470ce6bd0d5185c67
F src/build.c ca9e7a33b74f1bf2eb3a5f37f9d07dfed335469f2d70c0bd350e0dd42a50183a
F src/build.c 02cff9bb5b3eaf437cbad3f0e1b6c9612e4d4f355c9a766b8ebf121d95cee6d2
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6
@@ -485,7 +485,7 @@ F src/date.c b29b349d277e3d579dcc295b24c0a2caed83fd8f090a9f7cbe6070c0fd662384
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 793deaf88a0904f88285d93d6713c636d55ede0ffd9f08d10f4ea825531d367f
F src/delete.c 88047c8e59878c920fce14582bc1dde4d81157d1ca5ffdf36c2907e6d41996c4
F src/expr.c 8eed44d9de8a3b0fe1c9809bb75a02b65488774c8ba8685512d8f63adade18e5
F src/expr.c 217bee94b696a061fec28526c5d5ef3049536ace5c10a0a3ff7d15b0d3a9cd11
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 4b575423b0a5d4898b1a7868ce985cf1a8ad91c741c9abbb108ff02536d20f41
F src/func.c 2333eb4277f55a5efdc12ef754e7d7ec9105d257b2fd00301d23ce1e8fa67dc0
@@ -494,7 +494,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 8e4211d04eb460c0694d486c6ba1c068d468c6f653c3f237869a802ad82854de
F src/insert.c 92b07a7f7e682114948ce59fd6511ffec7672b508cc343a804ef6afee21b6c11
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 421310045bd78afefb772294a99e50f37d87ae578786a6169074e6291e30d969
F src/main.c 97d962ab1f830540043042e41085c5b85636a60e6ed95002c1a56b64f7eb6a0b
@@ -517,7 +517,7 @@ F src/os.c 669cc3839cc35d20f81faf0be1ab6d4581cea35e9d8f3a9d48a98d6571f7c285
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 13f983da988b6460ef3c4c22099c67ab0938291e543644ac4d99eccc8ba604f1
F src/os_unix.c 03bad4eb1e13946cb967f3a6cc0a0d350df8ea4b8d2212d528024a5f9abc90ea
F src/os_win.c e832e21e830c1f9409c9c54053939b6dcb14c1e92128b756204ce1e3e331d678
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 96436cb1920074d4ade120a1a8a9d0ae3f52df06651e21b7eccc5eae2f02b111
@@ -528,17 +528,17 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
F src/pragma.c 1b0db48177e52b256c003b8dc6ac708b1079a82cded944a23820574586a4731f
F src/pragma.h 8168e588536bffd95319451f34e9a754dc37d205ebe433031a7813c5b286beae
F src/prepare.c 8d4d6c8aa6afefc48027c54b41cdf134b4d6bc2fc4badbe483ad7fd9e1728a28
F src/printf.c ebf563cff3122f6a61149964b738b470196d3619df31d6a720d0ff72fcfd7c7b
F src/prepare.c bb996921a85590418f951f27566216646fad2d6856ba131b21594862055b1bd7
F src/printf.c 94b5419ad0a17269f76a9e968ca19cf9fa37617abed2e246fc48844e511b6bc6
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c d36a2b1639e1c33d7b508abfd3452a63e7fd81737f6f3940bfef085fca6f21f4
F src/resolve.c c2008519a0654f1e7490e9281ed0397d0f14bb840d81f0b96946248afcbdb25d
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c ee4b02ad8047c35891b7a612091beec21ae7a0155290dcbefb0824aed20c46f3
F src/shell.c.in cf2d24f54412c06e5fb34af7fabc748651125e1dceac29b740e91f06d23447b6
F src/select.c fb79ed71f8b8bbe9fefaba9b844f80700dea4f175ccac34c64a7b5cd75abc362
F src/shell.c.in c6e26593f2738eefded08a39204bf6b48db135cdfaa458c26ffe57055b4fe365
F src/sqlite.h.in 74342b41e9d68ff9e56b192009046f8dd0aa2bd76ce1a588f330de614ba61de7
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197
F src/sqliteInt.h 8878a88c18a013d1843638001d7fc56a8f99740f151fc7597b1641b61accf58c
F src/sqliteInt.h 04621e8c61c2bf4578d07e99cc5b5909b16d5e34600ed8297a8fd4d1a95afc4e
F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032
F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -598,18 +598,18 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c eee7bae3ec0bc4abee951554bf46a8ba567c0f7752ac90c820ed8afff4c612dc
F src/treeview.c 82c6391a3ba76215d4185fd4719a56ec4caf186a40c8a7b6e6ba4ae4467c2742
F src/treeview.c c5691babcd558baa136474b57a4aede45cf68daa3ed6637b981dde4b256e5b67
F src/trigger.c 4ada1037cc99777f647a882cdacbd1a4deb6567b69daf02946286401b88cdc04
F src/update.c 3199098455830fc2d8c8fc4ae3ec2ea513eef64339ae9a7048db62b21169bc7a
F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
F src/utf.c d7a61c1dfdac3eb091d43341a674032dca5a34e122f78ef0b5bd2d5a31967dde
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 3b6cedf7a0c69bd6e1acce832873952d416212d6293b18d03064e07d7a9b5118
F src/vacuum.c de9780b89fa4ee74c3534f60b94820e3179aca759ffc1338ee53cb4ea7693dd3
F src/vdbe.c e3dba0dee25bc92e871c13cac655260912b3be4abcc85b439259c9934b208da3
F src/vdbe.c a154f2785fbe4a1205944c647026445552ca3fa04ed1f313b05e614be205c061
F src/vdbe.h 07b8c636a87df8b6e58f29d6badd7f10d5844353deff1d7c88ed1c2bfe3bbd35
F src/vdbeInt.h 571413068b5ac07e2ed8ca7a02fa529622fd5455ae6981498376e5e492d2e5ef
F src/vdbeapi.c e467b75a710ea099f8d2d022abf601d2ccd05e28f63b44b12d93000b6a75f4a8
F src/vdbeaux.c 80626786d21296d9e7936186850343afe5fc6368ad9724a172e151788425a063
F src/vdbeaux.c 00746a04b3a1e917bab5e3846f0931820a5ded53cbe1648ba1ad57c0869c1ba3
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
F src/vdbemem.c 39b942ecca179f4f30a32b54579a85d74ccaefa5af2a0ad2700abe5ef0768b22
F src/vdbesort.c 2be76d26998ce2b3324cdcc9f6443728e54b6c7677c553ad909c7d7cfab587df
@@ -617,14 +617,14 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143
F src/vdbevtab.c ee5b4c902fdda2230f9503ac7b84c6d614c91e8f6f4dc1633e2e8dfef8ffb144
F src/vtab.c 7b452592ed2ee95dedb1f323d557cebede5a6f3b4558b21a5dca527e6ae9b12c
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 17ea0a319d3ead17ef3b16aa30f10f2626056893effea7e609a20a6661ffec1b
F src/wal.c 231044ecf7d5d78bc705af9dcec6c10ec59e891366362b6be54bb6a0bc7c17db
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed
F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9
F src/walker.c 3df26a33dc4f54e8771600fb7fdebe1ece0896c2ad68c30ab40b017aa4395049
F src/where.c 7bcc07ff56d03d73308245135d96de46d2faeaee628bd4badf0bae60ae6a31fe
F src/whereInt.h 6b874aa15f94e43a2cec1080be64d955b04deeafeac90ffb5d6975c0d511be3c
F src/wherecode.c 7b939de85d65cc4b4bfa197513136b9e0ae03167e3b82842ca5a0ba1055ba65d
F src/whereexpr.c 264d58971eaf8256eb5b0917bcd7fc7a1f1109fdda183a8382308a1b18a2dce7
F src/window.c 194fc168626f186a2b90dfe5edb534ab164cbeb6c4906177bfcdd5c188a0b53d
F src/window.c 7d19c08b62b70d5dc2ef4c098cc5ba611fac246a111fa36ebb39505415124b90
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -782,7 +782,7 @@ F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
F test/corruptL.test 13ef74a93223af25015d223add0df4c2d375f0b958b546a2a72033f2fdab7a70
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
F test/cost.test 51f4fcaae6e78ad5a57096831259ed6c760e2ac6876836e91c00030fad385b34
F test/cost.test 1d156ce9858780a966c062694687afe0343a0ed12d081d071fb57027e726bafc
F test/count.test e0699a15712bc2a4679d60e408921c2cce7f6365a30340e790c98e0f334a9c77
F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296
@@ -1029,7 +1029,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
F test/fuzzdata8.db 209623791b0ad72ab39110c867af2080a79004e493c4da14ad661e790b5d1ed8
F test/fuzzdata8.db 6acee588a3311994b57b226c9eac9e9e69f135cb8b000bd48fdb924e32041312
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
@@ -1067,10 +1067,10 @@ F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473a
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index6.test f172653b35b20233e59200e8b92a76db61bf7285437bf777b93b306ba26a47e7
F test/index7.test 1d764c0cca45f5a76150b08e127ccc8d52492cfa788b5fafed4be784a351b020
F test/index7.test b8a0ba2110fd517bb48c4e76d26d60f1ab2ed9e257b18d71f820d7e71e9f8570
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
F test/indexedby.test f54aac21c06948872010a956fd02de5178c362c7785a9887cf0b8616be17883b
F test/indexexpr1.test 284e119999d132cc8bf37735a928c9859b28e8e295d02b7a6a4f93977c7f9ba5
F test/indexexpr2.test dba11dbb0a58fcba4cd694f46b4004976123b81b0501f525d43c9be59f0207b1
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
@@ -1237,7 +1237,7 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test c83339862d72b6272f957905205f874e6eefdbad2823380452c4f0128fd3d906
F test/permutations.test 94bfbc9d32449fb3ef7d31962f8cdcd57dc59490681db84bd72236d4af7b5815
F test/pg_common.tcl 222a1bad1c41c308fa366313cd7b51b3be7e9b21c8736a421b974ac941693b54
F test/pragma.test 59becdfd720b80d463ab750f69f7118fde10dfd556aa5d554f3bf6b7e5ea7533
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
@@ -1246,7 +1246,7 @@ F test/pragma4.test 10c624e45a83c0096a82a7579a5ff658542391d3b77355192da6572c8c17
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
F test/printf.test 0300699733e53101b2ce48800518427249edd4053bb50fa0621c6607482f0fdb
F test/printf.test 1e0e469f5f8a09afa8a182f34647e3d9b8c01978cbbe2313a194ccc3a8471506
F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
@@ -1338,7 +1338,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 5bd10014ec494744f5e966a1521334e9d612119a0afcfa5251684a4e1f2ffc66
F test/shell1.test a1cf47c5e110560ff25a714570bfd53bfaceeb61db5cad3072a4064f17ebd10e
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
F test/shell4.test 1c6aef11daaa2d6830acaba3ac9cbec93fbc1c3d5530743a637f39b3987d08ce
@@ -1706,7 +1706,7 @@ F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test 75722434c486ac9e74718caa6cce234f45ba34c0b6c0f9555b29eb8bb5f6ade1
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
F test/where9.test 2c554b97bbdb2fdf26c57099f60db8a52bfcf7c147f2c256f9798fa0e267ca85
F test/where9.test 8e3e0ff42cc17156f52361a1c012281550d0d632912fec92d1d6df74db7a8e6d
F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
@@ -1727,7 +1727,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test a3504d44a3a125e35c53358cde1457d55bfc487bbe00f4c86bfed3a0bcc02140
F test/window1.test 49f81c25c065fd65b64cd2aaa96f20199fd5d8f847dd1c8151cfccae2aeae83f
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@@ -1866,10 +1866,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P ce36b6d1331edba5a921fef32553e2470a79bdb1f62d2cfd81190691c83d5b06
R b5a877f3e2a7ab538bc565ffd2aae787
T +bgcolor * #d0c0ff
T +sym-release *
T +sym-version-3.32.0 *
P 3c840b4df306e2db1da08673e9ede973b4cb6d2b3f9eeeab5835e39452ee3056
R 5a67d9ba1d91119ad620e46132adbad1
U drh
Z 4af13806b6e302c99aeddae94a54c013
Z 23a540eb57cb09221e33c4eabdced32a
+1 -1
View File
@@ -1 +1 @@
5998789c9c744bce92e4cff7636bba800a75574243d6977e1fc8281e360f8d5a
8b23d80271aab38abe42ee8b3ca4b746572ecef26c2a37b094b01560e6be9d45
+27 -3
View File
@@ -951,6 +951,30 @@ static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){
&statGetFuncdef, 0);
}
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
/* Add a comment to the most recent VDBE opcode that is the name
** of the k-th column of the pIdx index.
*/
static void analyzeVdbeCommentIndexWithColumnName(
Vdbe *v, /* Prepared statement under construction */
Index *pIdx, /* Index whose column is being loaded */
int k /* Which column index */
){
int i; /* Index of column in the table */
assert( k>=0 && k<pIdx->nColumn );
i = pIdx->aiColumn[k];
if( NEVER(i==XN_ROWID) ){
VdbeComment((v,"%s.rowid",pIdx->zName));
}else if( i==XN_EXPR ){
VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
}else{
VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zName));
}
}
#else
# define analyzeVdbeCommentIndexWithColumnName(a,b,c)
#endif /* SQLITE_DEBUG */
/*
** Generate code to do an analysis of all indices associated with
** a single table.
@@ -1167,7 +1191,7 @@ static void analyzeOneTable(
char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
analyzeVdbeCommentIndexWithColumnName(v,pIdx,i);
aGotoChng[i] =
sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
@@ -1188,7 +1212,7 @@ static void analyzeOneTable(
for(i=0; i<nColTest; i++){
sqlite3VdbeJumpHere(v, aGotoChng[i]);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
analyzeVdbeCommentIndexWithColumnName(v,pIdx,i);
}
sqlite3VdbeResolveLabel(v, endDistinctTest);
sqlite3DbFree(db, aGotoChng);
@@ -1214,7 +1238,7 @@ static void analyzeOneTable(
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
assert( k>=0 && k<pIdx->nColumn );
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
analyzeVdbeCommentIndexWithColumnName(v,pIdx,k);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
+29 -8
View File
@@ -207,12 +207,21 @@ void sqlite3FinishCoding(Parse *pParse){
*/
sqlite3AutoincrementBegin(pParse);
/* Code constant expressions that where factored out of inner loops */
/* Code constant expressions that where factored out of inner loops.
**
** The pConstExpr list might also contain expressions that we simply
** want to keep around until the Parse object is deleted. Such
** expressions have iConstExprReg==0. Do not generate code for
** those expressions, of course.
*/
if( pParse->pConstExpr ){
ExprList *pEL = pParse->pConstExpr;
pParse->okConstFactor = 0;
for(i=0; i<pEL->nExpr; i++){
sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
int iReg = pEL->a[i].u.iConstExprReg;
if( iReg>0 ){
sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
}
}
}
@@ -4047,9 +4056,10 @@ exit_create_index:
** are based on typical values found in actual indices.
*/
void sqlite3DefaultRowEst(Index *pIdx){
/* 10, 9, 8, 7, 6 */
LogEst aVal[] = { 33, 32, 30, 28, 26 };
/* 10, 9, 8, 7, 6 */
static const LogEst aVal[] = { 33, 32, 30, 28, 26 };
LogEst *a = pIdx->aiRowLogEst;
LogEst x;
int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
int i;
@@ -4058,10 +4068,21 @@ void sqlite3DefaultRowEst(Index *pIdx){
/* Set the first entry (number of rows in the index) to the estimated
** number of rows in the table, or half the number of rows in the table
** for a partial index. But do not let the estimate drop below 10. */
a[0] = pIdx->pTable->nRowLogEst;
if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10; assert( 10==sqlite3LogEst(2) );
if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) );
** for a partial index.
**
** 2020-05-27: If some of the stat data is coming from the sqlite_stat1
** table but other parts we are having to guess at, then do not let the
** estimated number of rows in the table be less than 1000 (LogEst 99).
** Failure to do this can cause the indexes for which we do not have
** stat1 data to be ignored by the query planner. tag-20200527-1
*/
x = pIdx->pTable->nRowLogEst;
assert( 99==sqlite3LogEst(1000) );
if( x<99 ){
pIdx->pTable->nRowLogEst = x = 99;
}
if( pIdx->pPartIdxWhere!=0 ) x -= 10; assert( 10==sqlite3LogEst(2) );
a[0] = x;
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
** 6 and each subsequent value (if any) is 5. */
+81 -22
View File
@@ -52,7 +52,12 @@ char sqlite3ExprAffinity(const Expr *pExpr){
op = pExpr->op;
if( op==TK_SELECT ){
assert( pExpr->flags&EP_xIsSelect );
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
if( ALWAYS(pExpr->x.pSelect)
&& pExpr->x.pSelect->pEList
&& ALWAYS(pExpr->x.pSelect->pEList->a[0].pExpr)
){
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
}
if( op==TK_REGISTER ) op = pExpr->op2;
#ifndef SQLITE_OMIT_CAST
@@ -2552,7 +2557,7 @@ int sqlite3FindInIndex(
if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
sqlite3 *db = pParse->db; /* Database connection */
Table *pTab; /* Table <table>. */
i16 iDb; /* Database idx for pTab */
int iDb; /* Database idx for pTab */
ExprList *pEList = p->pEList;
int nExpr = pEList->nExpr;
@@ -2563,6 +2568,7 @@ int sqlite3FindInIndex(
/* Code an OP_Transaction and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED );
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
@@ -3796,10 +3802,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
int p5 = 0;
assert( target>0 && target<=pParse->nMem );
if( v==0 ){
assert( pParse->db->mallocFailed );
return 0;
}
assert( v!=0 );
expr_code_doover:
if( pExpr==0 ){
@@ -3811,7 +3814,10 @@ expr_code_doover:
switch( op ){
case TK_AGG_COLUMN: {
AggInfo *pAggInfo = pExpr->pAggInfo;
struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
struct AggInfo_col *pCol;
assert( pAggInfo!=0 );
assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
pCol = &pAggInfo->aCol[pExpr->iAgg];
if( !pAggInfo->directMode ){
assert( pCol->iMem>0 );
return pCol->iMem;
@@ -4111,7 +4117,10 @@ expr_code_doover:
}
case TK_AGG_FUNCTION: {
AggInfo *pInfo = pExpr->pAggInfo;
if( pInfo==0 ){
if( pInfo==0
|| NEVER(pExpr->iAgg<0)
|| NEVER(pExpr->iAgg>=pInfo->nFunc)
){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
}else{
@@ -4623,9 +4632,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) );
assert( target>0 && target<=pParse->nMem );
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
if( inReg!=target && pParse->pVdbe ){
if( pParse->pVdbe==0 ) return;
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
if( inReg!=target ){
u8 op;
if( ExprHasProperty(pExpr,EP_Subquery) ){
op = OP_Copy;
@@ -5704,6 +5714,64 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
return cnt.nThis>0 || cnt.nOther==0;
}
/*
** This is a Walker expression node callback.
**
** For Expr nodes that contain pAggInfo pointers, make sure the AggInfo
** object that is referenced does not refer directly to the Expr. If
** it does, make a copy. This is done because the pExpr argument is
** subject to change.
**
** The copy is stored on pParse->pConstExpr with a register number of 0.
** This will cause the expression to be deleted automatically when the
** Parse object is destroyed, but the zero register number means that it
** will not generate any code in the preamble.
*/
static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
if( ALWAYS(!ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced))
&& pExpr->pAggInfo!=0
){
AggInfo *pAggInfo = pExpr->pAggInfo;
int iAgg = pExpr->iAgg;
Parse *pParse = pWalker->pParse;
sqlite3 *db = pParse->db;
assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION );
if( pExpr->op==TK_AGG_COLUMN ){
assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
if( pAggInfo->aCol[iAgg].pExpr==pExpr ){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aCol[iAgg].pExpr = pExpr;
pParse->pConstExpr =
sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
}
}
}else{
assert( iAgg>=0 && iAgg<pAggInfo->nFunc );
if( pAggInfo->aFunc[iAgg].pExpr==pExpr ){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aFunc[iAgg].pExpr = pExpr;
pParse->pConstExpr =
sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
}
}
}
}
return WRC_Continue;
}
/*
** Initialize a Walker object so that will persist AggInfo entries referenced
** by the tree that is walked.
*/
void sqlite3AggInfoPersistWalkerInit(Walker *pWalker, Parse *pParse){
memset(pWalker, 0, sizeof(*pWalker));
pWalker->pParse = pParse;
pWalker->xExprCallback = agginfoPersistExprCb;
pWalker->xSelectCallback = sqlite3SelectWalkNoop;
}
/*
** Add a new element to the pAggInfo->aCol[] array. Return the index of
** the new element. Return a negative number if malloc fails.
@@ -5734,7 +5802,7 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
&i
);
return i;
}
}
/*
** This is the xExprCallback for a tree walker. It is used to
@@ -5867,15 +5935,6 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
}
return WRC_Continue;
}
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
UNUSED_PARAMETER(pSelect);
pWalker->walkerDepth++;
return WRC_Continue;
}
static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
UNUSED_PARAMETER(pSelect);
pWalker->walkerDepth--;
}
/*
** Analyze the pExpr expression looking for aggregate functions and
@@ -5889,8 +5948,8 @@ static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
Walker w;
w.xExprCallback = analyzeAggregate;
w.xSelectCallback = analyzeAggregatesInSelect;
w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
w.xSelectCallback = sqlite3WalkerDepthIncrease;
w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
w.walkerDepth = 0;
w.u.pNC = pNC;
w.pParse = 0;
+1 -1
View File
@@ -1944,7 +1944,7 @@ void sqlite3GenerateConstraintChecks(
sqlite3TableAffinity(v, pTab, regNewData+1);
bAffinityDone = 1;
}
VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
VdbeNoopComment((v, "prep index %s", pIdx->zName));
iThisCur = iIdxCur+ix;
+4 -1
View File
@@ -4836,7 +4836,10 @@ static int unixShmLock(
**
** In other words, if this is a blocking lock, none of the locks that
** occur later in the above list than the lock being obtained may be
** held. */
** held.
**
** It is not permitted to block on the RECOVER lock.
*/
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
(ofst!=2) /* not RECOVER */
+21 -5
View File
@@ -504,17 +504,18 @@ static void schemaIsValid(Parse *pParse){
** attached database is returned.
*/
int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
int i = -1000000;
int i = -32768;
/* If pSchema is NULL, then return -1000000. This happens when code in
/* If pSchema is NULL, then return -32768. This happens when code in
** expr.c is trying to resolve a reference to a transient table (i.e. one
** created by a sub-select). In this case the return value of this
** function should never be used.
**
** We return -1000000 instead of the more usual -1 simply because using
** -1000000 as the incorrect index into db->aDb[] is much
** We return -32768 instead of the more usual -1 simply because using
** -32768 as the incorrect index into db->aDb[] is much
** more likely to cause a segfault than -1 (of course there are assert()
** statements too, but it never hurts to play the odds).
** statements too, but it never hurts to play the odds) and
** -32768 will still fit into a 16-bit signed integer.
*/
assert( sqlite3_mutex_held(db->mutex) );
if( pSchema ){
@@ -529,11 +530,26 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
return i;
}
/*
** Deallocate a single AggInfo object
*/
static void agginfoFree(sqlite3 *db, AggInfo *p){
sqlite3DbFree(db, p->aCol);
sqlite3DbFree(db, p->aFunc);
sqlite3DbFree(db, p);
}
/*
** Free all memory allocations in the pParse object
*/
void sqlite3ParserReset(Parse *pParse){
sqlite3 *db = pParse->db;
AggInfo *pThis = pParse->pAggList;
while( pThis ){
AggInfo *pNext = pThis->pNext;
agginfoFree(db, pThis);
pThis = pNext;
}
sqlite3DbFree(db, pParse->aLabel);
sqlite3ExprListDelete(db, pParse->pConstExpr);
if( db ){
+15 -1
View File
@@ -194,6 +194,13 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
#endif
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
/*
** Hard limit on the precision of floating-point conversions.
*/
#ifndef SQLITE_PRINTF_PRECISION_LIMIT
# define SQLITE_FP_PRECISION_LIMIT 100000000
#endif
/*
** Render a string given by "fmt" into the StrAccum object.
*/
@@ -394,6 +401,8 @@ void sqlite3_str_vappendf(
** xtype The class of the conversion.
** infop Pointer to the appropriate info struct.
*/
assert( width>=0 );
assert( precision>=(-1) );
switch( xtype ){
case etPOINTER:
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
@@ -515,6 +524,11 @@ void sqlite3_str_vappendf(
length = 0;
#else
if( precision<0 ) precision = 6; /* Set default precision */
#ifdef SQLITE_FP_PRECISION_LIMIT
if( precision>SQLITE_FP_PRECISION_LIMIT ){
precision = SQLITE_FP_PRECISION_LIMIT;
}
#endif
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
@@ -797,7 +811,7 @@ void sqlite3_str_vappendf(
}
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
/* For %q, %Q, and %w, the precision is the number of byte (or
/* For %q, %Q, and %w, the precision is the number of bytes (or
** characters if the ! flags is present) to use from the input.
** Because of the extra quoting characters inserted, the number
** of output characters may be larger than the precision.
+2
View File
@@ -24,6 +24,8 @@
**
** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
** is a helper function - a callback for the tree walker.
**
** See also the sqlite3WindowExtraAggFuncDepth() routine in window.c
*/
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
+82 -76
View File
@@ -138,9 +138,9 @@ Select *sqlite3SelectNew(
u32 selFlags, /* Flag parameters, such as SF_Distinct */
Expr *pLimit /* LIMIT value. NULL means not used */
){
Select *pNew;
Select *pNew, *pAllocated;
Select standin;
pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
pAllocated = pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
if( pNew==0 ){
assert( pParse->db->mallocFailed );
pNew = &standin;
@@ -174,12 +174,11 @@ Select *sqlite3SelectNew(
#endif
if( pParse->db->mallocFailed ) {
clearSelect(pParse->db, pNew, pNew!=&standin);
pNew = 0;
pAllocated = 0;
}else{
assert( pNew->pSrc!=0 || pParse->nErr>0 );
}
assert( pNew!=&standin );
return pNew;
return pAllocated;
}
@@ -3792,6 +3791,7 @@ static int flattenSubquery(
Expr *pWhere; /* The WHERE clause */
struct SrcList_item *pSubitem; /* The subquery */
sqlite3 *db = pParse->db;
Walker w; /* Walker to persist agginfo data */
/* Check to see if flattening is permitted. Return 0 if not.
*/
@@ -4166,6 +4166,8 @@ static int flattenSubquery(
/* Finially, delete what is left of the subquery and return
** success.
*/
sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlite3WalkSelect(&w,pSub1);
sqlite3SelectDelete(db, pSub1);
#if SELECTTRACE_ENABLED
@@ -5229,29 +5231,6 @@ static int selectExpander(Walker *pWalker, Select *p){
return WRC_Continue;
}
/*
** No-op routine for the parse-tree walker.
**
** When this routine is the Walker.xExprCallback then expression trees
** are walked without any actions being taken at each node. Presumably,
** when this routine is used for Walker.xExprCallback then
** Walker.xSelectCallback is set to do something useful for every
** subquery in the parser tree.
*/
int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
return WRC_Continue;
}
/*
** No-op routine for the parse-tree walker for SELECT statements.
** subquery in the parser tree.
*/
int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
return WRC_Continue;
}
#if SQLITE_DEBUG
/*
** Always assert. This xSelectCallback2 implementation proves that the
@@ -5773,10 +5752,10 @@ int sqlite3Select(
Expr *pWhere; /* The WHERE clause. May be NULL */
ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
Expr *pHaving; /* The HAVING clause. May be NULL */
AggInfo *pAggInfo = 0; /* Aggregate information */
int rc = 1; /* Value to return from this function */
DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
SortCtx sSort; /* Info on how to code the ORDER BY clause */
AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
sqlite3 *db; /* The database connection */
ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */
@@ -5788,7 +5767,6 @@ int sqlite3Select(
return 1;
}
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
memset(&sAggInfo, 0, sizeof(sAggInfo));
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
if( sqlite3SelectTrace & 0x100 ){
@@ -6378,14 +6356,20 @@ int sqlite3Select(
** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
** SELECT statement.
*/
pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) );
if( pAggInfo==0 ){
goto select_end;
}
pAggInfo->pNext = pParse->pAggList;
pParse->pAggList = pAggInfo;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
sNC.uNC.pAggInfo = &sAggInfo;
sNC.uNC.pAggInfo = pAggInfo;
VVA_ONLY( sNC.ncFlags = NC_UAggInfo; )
sAggInfo.mnReg = pParse->nMem+1;
sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
sAggInfo.pGroupBy = pGroupBy;
pAggInfo->mnReg = pParse->nMem+1;
pAggInfo->nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
pAggInfo->pGroupBy = pGroupBy;
sqlite3ExprAnalyzeAggList(&sNC, pEList);
sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
if( pHaving ){
@@ -6398,14 +6382,14 @@ int sqlite3Select(
}
sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
}
sAggInfo.nAccumulator = sAggInfo.nColumn;
if( p->pGroupBy==0 && p->pHaving==0 && sAggInfo.nFunc==1 ){
minMaxFlag = minMaxQuery(db, sAggInfo.aFunc[0].pExpr, &pMinMaxOrderBy);
pAggInfo->nAccumulator = pAggInfo->nColumn;
if( p->pGroupBy==0 && p->pHaving==0 && pAggInfo->nFunc==1 ){
minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pExpr, &pMinMaxOrderBy);
}else{
minMaxFlag = WHERE_ORDERBY_NORMAL;
}
for(i=0; i<sAggInfo.nFunc; i++){
Expr *pExpr = sAggInfo.aFunc[i].pExpr;
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pExpr;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
sNC.ncFlags |= NC_InAggFunc;
sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList);
@@ -6417,22 +6401,22 @@ int sqlite3Select(
#endif
sNC.ncFlags &= ~NC_InAggFunc;
}
sAggInfo.mxReg = pParse->nMem;
pAggInfo->mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
int ii;
SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n"));
SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
sqlite3TreeViewSelect(0, p, 0);
for(ii=0; ii<sAggInfo.nColumn; ii++){
for(ii=0; ii<pAggInfo->nColumn; ii++){
sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
ii, sAggInfo.aCol[ii].iMem);
sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0);
ii, pAggInfo->aCol[ii].iMem);
sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pExpr, 0);
}
for(ii=0; ii<sAggInfo.nFunc; ii++){
for(ii=0; ii<pAggInfo->nFunc; ii++){
sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n",
ii, sAggInfo.aFunc[ii].iMem);
sqlite3TreeViewExpr(0, sAggInfo.aFunc[ii].pExpr, 0);
ii, pAggInfo->aFunc[ii].iMem);
sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pExpr, 0);
}
}
#endif
@@ -6457,10 +6441,11 @@ int sqlite3Select(
** that we do not need it after all, the OP_SorterOpen instruction
** will be converted into a Noop.
*/
sAggInfo.sortingIdx = pParse->nTab++;
pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pGroupBy,0,sAggInfo.nColumn);
pAggInfo->sortingIdx = pParse->nTab++;
pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pGroupBy,
0, pAggInfo->nColumn);
addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
pAggInfo->sortingIdx, pAggInfo->nSortingColumn,
0, (char*)pKeyInfo, P4_KEYINFO);
/* Initialize memory locations used by GROUP BY aggregate processing
@@ -6515,8 +6500,8 @@ int sqlite3Select(
nGroupBy = pGroupBy->nExpr;
nCol = nGroupBy;
j = nGroupBy;
for(i=0; i<sAggInfo.nColumn; i++){
if( sAggInfo.aCol[i].iSorterColumn>=j ){
for(i=0; i<pAggInfo->nColumn; i++){
if( pAggInfo->aCol[i].iSorterColumn>=j ){
nCol++;
j++;
}
@@ -6524,8 +6509,8 @@ int sqlite3Select(
regBase = sqlite3GetTempRange(pParse, nCol);
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0);
j = nGroupBy;
for(i=0; i<sAggInfo.nColumn; i++){
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
for(i=0; i<pAggInfo->nColumn; i++){
struct AggInfo_col *pCol = &pAggInfo->aCol[i];
if( pCol->iSorterColumn>=j ){
int r1 = j + regBase;
sqlite3ExprCodeGetColumnOfTable(v,
@@ -6535,16 +6520,16 @@ int sqlite3Select(
}
regRecord = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nCol);
sqlite3WhereEnd(pWInfo);
sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++;
sortOut = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd);
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
sAggInfo.useSortingIdx = 1;
pAggInfo->useSortingIdx = 1;
}
/* If the index or temporary table used by the GROUP BY sort
@@ -6568,14 +6553,14 @@ int sqlite3Select(
*/
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
sqlite3VdbeAddOp3(v, OP_SorterData, pAggInfo->sortingIdx,
sortOut, sortPTab);
}
for(j=0; j<pGroupBy->nExpr; j++){
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
}else{
sAggInfo.directMode = 1;
pAggInfo->directMode = 1;
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
}
}
@@ -6605,14 +6590,14 @@ int sqlite3Select(
** the current row
*/
sqlite3VdbeJumpHere(v, addr1);
updateAccumulator(pParse, iUseFlag, &sAggInfo);
updateAccumulator(pParse, iUseFlag, pAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
VdbeComment((v, "indicate data in accumulator"));
/* End of the loop
*/
if( groupBySort ){
sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx, addrTopOfLoop);
VdbeCoverage(v);
}else{
sqlite3WhereEnd(pWInfo);
@@ -6645,7 +6630,7 @@ int sqlite3Select(
VdbeCoverage(v);
VdbeComment((v, "Groupby result generator entry point"));
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
finalizeAggFunctions(pParse, &sAggInfo);
finalizeAggFunctions(pParse, pAggInfo);
sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
selectInnerLoop(pParse, p, -1, &sSort,
&sDistinct, pDest,
@@ -6656,7 +6641,7 @@ int sqlite3Select(
/* Generate a subroutine that will reset the group-by accumulator
*/
sqlite3VdbeResolveLabel(v, addrReset);
resetAccumulator(pParse, &sAggInfo);
resetAccumulator(pParse, pAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
@@ -6664,7 +6649,7 @@ int sqlite3Select(
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
Table *pTab;
if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
/* If isSimpleCount() returns a pointer to a Table structure, then
** the SQL statement is of the form:
**
@@ -6719,7 +6704,7 @@ int sqlite3Select(
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
}
sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem);
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
explainSimpleCount(pParse, pTab, pBest);
}else{
@@ -6734,12 +6719,16 @@ int sqlite3Select(
** first row visited by the aggregate, so that they are updated at
** least once even if the FILTER clause means the min() or max()
** function visits zero rows. */
if( sAggInfo.nAccumulator ){
for(i=0; i<sAggInfo.nFunc; i++){
if( ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_WinFunc) ) continue;
if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break;
if( pAggInfo->nAccumulator ){
for(i=0; i<pAggInfo->nFunc; i++){
if( ExprHasProperty(pAggInfo->aFunc[i].pExpr, EP_WinFunc) ){
continue;
}
if( pAggInfo->aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ){
break;
}
}
if( i==sAggInfo.nFunc ){
if( i==pAggInfo->nFunc ){
regAcc = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
@@ -6750,7 +6739,7 @@ int sqlite3Select(
** of output.
*/
assert( p->pGroupBy==0 );
resetAccumulator(pParse, &sAggInfo);
resetAccumulator(pParse, pAggInfo);
/* If this query is a candidate for the min/max optimization, then
** minMaxFlag will have been previously set to either
@@ -6766,7 +6755,7 @@ int sqlite3Select(
if( pWInfo==0 ){
goto select_end;
}
updateAccumulator(pParse, regAcc, &sAggInfo);
updateAccumulator(pParse, regAcc, pAggInfo);
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
if( sqlite3WhereIsOrdered(pWInfo)>0 ){
sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo));
@@ -6774,7 +6763,7 @@ int sqlite3Select(
(minMaxFlag==WHERE_ORDERBY_MIN?"min":"max")));
}
sqlite3WhereEnd(pWInfo);
finalizeAggFunctions(pParse, &sAggInfo);
finalizeAggFunctions(pParse, pAggInfo);
}
sSort.pOrderBy = 0;
@@ -6813,8 +6802,25 @@ int sqlite3Select(
*/
select_end:
sqlite3ExprListDelete(db, pMinMaxOrderBy);
sqlite3DbFree(db, sAggInfo.aCol);
sqlite3DbFree(db, sAggInfo.aFunc);
#ifdef SQLITE_DEBUG
if( pAggInfo ){
for(i=0; i<pAggInfo->nColumn; i++){
Expr *pExpr = pAggInfo->aCol[i].pExpr;
assert( pExpr!=0 || db->mallocFailed );
if( pExpr==0 ) continue;
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pExpr;
assert( pExpr!=0 || db->mallocFailed );
if( pExpr==0 ) continue;
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
}
#endif
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end processing\n"));
if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
+435 -106
View File
@@ -1035,18 +1035,6 @@ struct OpenSession {
};
#endif
/*
** Shell output mode information from before ".explain on",
** saved so that it can be restored by ".explain off"
*/
typedef struct SavedModeInfo SavedModeInfo;
struct SavedModeInfo {
int valid; /* Is there legit data in here? */
int mode; /* Mode prior to ".explain on" */
int showHeader; /* The ".header" setting prior to ".explain on" */
int colWidth[100]; /* Column widths prior to ".explain on" */
};
typedef struct ExpertInfo ExpertInfo;
struct ExpertInfo {
sqlite3expert *pExpert;
@@ -1116,8 +1104,9 @@ struct ShellState {
char rowSeparator[20]; /* Row separator character for MODE_Ascii */
char colSepPrior[20]; /* Saved column separator */
char rowSepPrior[20]; /* Saved row separator */
int colWidth[100]; /* Requested width of each column when in column mode*/
int actualWidth[100]; /* Actual width of each column */
int *colWidth; /* Requested width of each column in columnar modes */
int *actualWidth; /* Actual width of each column */
int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
char nullValue[20]; /* The text to print when a NULL comes back from
** the database */
char outfile[FILENAME_MAX]; /* Filename for *out */
@@ -1178,6 +1167,7 @@ struct ShellState {
#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
/*
** Macros for testing and setting shellFlgs
@@ -1202,6 +1192,10 @@ struct ShellState {
#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
#define MODE_Pretty 11 /* Pretty-print schemas */
#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
#define MODE_Json 13 /* Output JSON */
#define MODE_Markdown 14 /* Markdown formatting */
#define MODE_Table 15 /* MySQL-style table formatting */
#define MODE_Box 16 /* Unicode box-drawing characters */
static const char *modeDescr[] = {
"line",
@@ -1216,7 +1210,11 @@ static const char *modeDescr[] = {
"explain",
"ascii",
"prettyprint",
"eqp"
"eqp",
"json",
"markdown",
"table",
"box"
};
/*
@@ -1584,6 +1582,40 @@ static void output_c_string(FILE *out, const char *z){
fputc('"', out);
}
/*
** Output the given string as a quoted according to JSON quoting rules.
*/
static void output_json_string(FILE *out, const char *z, int n){
unsigned int c;
if( n<0 ) n = (int)strlen(z);
fputc('"', out);
while( n-- ){
c = *(z++);
if( c=='\\' || c=='"' ){
fputc('\\', out);
fputc(c, out);
}else if( c<=0x1f ){
fputc('\\', out);
if( c=='\b' ){
fputc('b', out);
}else if( c=='\f' ){
fputc('f', out);
}else if( c=='\n' ){
fputc('n', out);
}else if( c=='\r' ){
fputc('r', out);
}else if( c=='\t' ){
fputc('t', out);
}else{
raw_printf(out, "u%04x",c);
}
}else{
fputc(c, out);
}
}
fputc('"', out);
}
/*
** Output the given string with characters that are special to
** HTML escaped.
@@ -1893,6 +1925,40 @@ static int progress_handler(void *pClientData) {
}
#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
/*
** Print N dashes
*/
static void print_dashes(FILE *out, int N){
const char zDash[] = "--------------------------------------------------";
const int nDash = sizeof(zDash) - 1;
while( N>nDash ){
fputs(zDash, out);
N -= nDash;
}
raw_printf(out, "%.*s", N, zDash);
}
/*
** Print a markdown or table-style row separator using ascii-art
*/
static void print_row_separator(
ShellState *p,
int nArg,
const char *zSep
){
int i;
if( nArg>0 ){
fputs(zSep, p->out);
print_dashes(p->out, p->actualWidth[0]+2);
for(i=1; i<nArg; i++){
fputs(zSep, p->out);
print_dashes(p->out, p->actualWidth[i]+2);
}
fputs(zSep, p->out);
}
fputs("\n", p->out);
}
/*
** This is the callback routine that the shell
** invokes for each row of a query result.
@@ -1902,7 +1968,7 @@ static int shell_callback(
int nArg, /* Number of result columns */
char **azArg, /* Text of each result column */
char **azCol, /* Column names */
int *aiType /* Column types */
int *aiType /* Column types. Might be NULL */
){
int i;
ShellState *p = (ShellState*)pArg;
@@ -1923,71 +1989,27 @@ static int shell_callback(
}
break;
}
case MODE_Explain:
case MODE_Column: {
static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};
const int *colWidth;
int showHdr;
char *rowSep;
int nWidth;
if( p->cMode==MODE_Column ){
colWidth = p->colWidth;
nWidth = ArraySize(p->colWidth);
showHdr = p->showHeader;
rowSep = p->rowSeparator;
}else{
colWidth = aExplainWidths;
nWidth = ArraySize(aExplainWidths);
showHdr = 1;
rowSep = SEP_Row;
case MODE_Explain: {
static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
if( nArg>ArraySize(aExplainWidth) ){
nArg = ArraySize(aExplainWidth);
}
if( p->cnt++==0 ){
for(i=0; i<nArg; i++){
int w, n;
if( i<nWidth ){
w = colWidth[i];
}else{
w = 0;
}
if( w==0 ){
w = strlenChar(azCol[i] ? azCol[i] : "");
if( w<10 ) w = 10;
n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
if( w<n ) w = n;
}
if( i<ArraySize(p->actualWidth) ){
p->actualWidth[i] = w;
}
if( showHdr ){
utf8_width_print(p->out, w, azCol[i]);
utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
}
int w = aExplainWidth[i];
utf8_width_print(p->out, w, azCol[i]);
fputs(i==nArg-1 ? "\n" : " ", p->out);
}
if( showHdr ){
for(i=0; i<nArg; i++){
int w;
if( i<ArraySize(p->actualWidth) ){
w = p->actualWidth[i];
if( w<0 ) w = -w;
}else{
w = 10;
}
utf8_printf(p->out,"%-*.*s%s",w,w,
"----------------------------------------------------------"
"----------------------------------------------------------",
i==nArg-1 ? rowSep : " ");
}
for(i=0; i<nArg; i++){
int w = aExplainWidth[i];
print_dashes(p->out, w);
fputs(i==nArg-1 ? "\n" : " ", p->out);
}
}
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
int w;
if( i<ArraySize(p->actualWidth) ){
w = p->actualWidth[i];
}else{
w = 10;
}
if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
int w = aExplainWidth[i];
if( azArg[i] && strlenChar(azArg[i])>w ){
w = strlenChar(azArg[i]);
}
if( i==1 && p->aiIndent && p->pStmt ){
@@ -1997,7 +2019,7 @@ static int shell_callback(
p->iIndent++;
}
utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
fputs(i==nArg-1 ? "\n" : " ", p->out);
}
break;
}
@@ -2201,18 +2223,60 @@ static int shell_callback(
raw_printf(p->out,");\n");
break;
}
case MODE_Json: {
if( azArg==0 ) break;
if( p->cnt==0 ){
fputs("[{", p->out);
}else{
fputs(",\n{", p->out);
}
p->cnt++;
for(i=0; i<nArg; i++){
output_json_string(p->out, azCol[i], -1);
putc(':', p->out);
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
fputs("null",p->out);
}else if( aiType && aiType[i]==SQLITE_FLOAT ){
char z[50];
double r = sqlite3_column_double(p->pStmt, i);
sqlite3_uint64 ur;
memcpy(&ur,&r,sizeof(r));
if( ur==0x7ff0000000000000LL ){
raw_printf(p->out, "1e999");
}else if( ur==0xfff0000000000000LL ){
raw_printf(p->out, "-1e999");
}else{
sqlite3_snprintf(50,z,"%!.20g", r);
raw_printf(p->out, "%s", z);
}
}else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
const void *pBlob = sqlite3_column_blob(p->pStmt, i);
int nBlob = sqlite3_column_bytes(p->pStmt, i);
output_json_string(p->out, pBlob, nBlob);
}else if( aiType && aiType[i]==SQLITE_TEXT ){
output_json_string(p->out, azArg[i], -1);
}else{
utf8_printf(p->out,"%s", azArg[i]);
}
if( i<nArg-1 ){
putc(',', p->out);
}
}
putc('}', p->out);
break;
}
case MODE_Quote: {
if( azArg==0 ) break;
if( p->cnt==0 && p->showHeader ){
for(i=0; i<nArg; i++){
if( i>0 ) raw_printf(p->out, ",");
if( i>0 ) fputs(p->colSeparator, p->out);
output_quoted_string(p->out, azCol[i]);
}
raw_printf(p->out,"\n");
fputs(p->rowSeparator, p->out);
}
p->cnt++;
for(i=0; i<nArg; i++){
if( i>0 ) raw_printf(p->out, ",");
if( i>0 ) fputs(p->colSeparator, p->out);
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
utf8_printf(p->out,"NULL");
}else if( aiType && aiType[i]==SQLITE_TEXT ){
@@ -2234,7 +2298,7 @@ static int shell_callback(
output_quoted_string(p->out, azArg[i]);
}
}
raw_printf(p->out,"\n");
fputs(p->rowSeparator, p->out);
break;
}
case MODE_Ascii: {
@@ -2890,6 +2954,214 @@ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
sqlite3_finalize(pQ);
}
/*
** UTF8 box-drawing characters. Imagine box lines like this:
**
** 1
** |
** 4 --+-- 2
** |
** 3
**
** Each box characters has between 2 and 4 of the lines leading from
** the center. The characters are here identified by the numbers of
** their corresponding lines.
*/
#define BOX_24 "\342\224\200" /* U+2500 --- */
#define BOX_13 "\342\224\202" /* U+2502 | */
#define BOX_23 "\342\224\214" /* U+250c ,- */
#define BOX_34 "\342\224\220" /* U+2510 -, */
#define BOX_12 "\342\224\224" /* U+2514 '- */
#define BOX_14 "\342\224\230" /* U+2518 -' */
#define BOX_123 "\342\224\234" /* U+251c |- */
#define BOX_134 "\342\224\244" /* U+2524 -| */
#define BOX_234 "\342\224\254" /* U+252c -,- */
#define BOX_124 "\342\224\264" /* U+2534 -'- */
#define BOX_1234 "\342\224\274" /* U+253c -|- */
/* Draw horizontal line N characters long using unicode box
** characters
*/
static void print_box_line(FILE *out, int N){
const char zDash[] =
BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
const int nDash = sizeof(zDash) - 1;
N *= 3;
while( N>nDash ){
utf8_printf(out, zDash);
N -= nDash;
}
utf8_printf(out, "%.*s", N, zDash);
}
/*
** Draw a horizontal separator for a MODE_Box table.
*/
static void print_box_row_separator(
ShellState *p,
int nArg,
const char *zSep1,
const char *zSep2,
const char *zSep3
){
int i;
if( nArg>0 ){
utf8_printf(p->out, "%s", zSep1);
print_box_line(p->out, p->actualWidth[0]+2);
for(i=1; i<nArg; i++){
utf8_printf(p->out, "%s", zSep2);
print_box_line(p->out, p->actualWidth[i]+2);
}
utf8_printf(p->out, "%s", zSep3);
}
fputs("\n", p->out);
}
/*
** Run a prepared statement and output the result in one of the
** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
** or MODE_Box.
**
** This is different from ordinary exec_prepared_stmt() in that
** it has to run the entire query and gather the results into memory
** first, in order to determine column widths, before providing
** any output.
*/
static void exec_prepared_stmt_columnar(
ShellState *p, /* Pointer to ShellState */
sqlite3_stmt *pStmt /* Statment to run */
){
int nRow = 0;
int nColumn = 0;
char **azData = 0;
char *zMsg = 0;
const char *z;
int rc;
int i, j, nTotal, w, n;
const char *colSep = 0;
const char *rowSep = 0;
rc = sqlite3_get_table(p->db, sqlite3_sql(pStmt),
&azData, &nRow, &nColumn, &zMsg);
if( rc ){
utf8_printf(p->out, "ERROR: %s\n", zMsg);
sqlite3_free(zMsg);
sqlite3_free_table(azData);
return;
}
if( nRow==0 || nColumn==0 ){
sqlite3_free_table(azData);
return;
}
if( nColumn>p->nWidth ){
p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
if( p->colWidth==0 ) shell_out_of_memory();
for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
p->nWidth = nColumn;
p->actualWidth = &p->colWidth[nColumn];
}
memset(p->actualWidth, 0, nColumn*sizeof(int));
for(i=0; i<nColumn; i++){
w = p->colWidth[i];
if( w<0 ) w = -w;
p->actualWidth[i] = w;
}
nTotal = nColumn*(nRow+1);
for(i=0; i<nTotal; i++){
z = azData[i];
if( z==0 ) z = p->nullValue;
n = strlenChar(z);
j = i%nColumn;
if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
}
switch( p->cMode ){
case MODE_Column: {
colSep = " ";
rowSep = "\n";
if( p->showHeader ){
for(i=0; i<nColumn; i++){
w = p->actualWidth[i];
if( p->colWidth[i]<0 ) w = -w;
utf8_width_print(p->out, w, azData[i]);
fputs(i==nColumn-1?"\n":" ", p->out);
}
for(i=0; i<nColumn; i++){
print_dashes(p->out, p->actualWidth[i]);
fputs(i==nColumn-1?"\n":" ", p->out);
}
}
break;
}
case MODE_Table: {
colSep = " | ";
rowSep = " |\n";
print_row_separator(p, nColumn, "+");
fputs("| ", p->out);
for(i=0; i<nColumn; i++){
w = p->actualWidth[i];
n = strlenChar(azData[i]);
utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
fputs(i==nColumn-1?" |\n":" | ", p->out);
}
print_row_separator(p, nColumn, "+");
break;
}
case MODE_Markdown: {
colSep = " | ";
rowSep = " |\n";
fputs("| ", p->out);
for(i=0; i<nColumn; i++){
w = p->actualWidth[i];
n = strlenChar(azData[i]);
utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
fputs(i==nColumn-1?" |\n":" | ", p->out);
}
print_row_separator(p, nColumn, "|");
break;
}
case MODE_Box: {
colSep = " " BOX_13 " ";
rowSep = " " BOX_13 "\n";
print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
utf8_printf(p->out, BOX_13 " ");
for(i=0; i<nColumn; i++){
w = p->actualWidth[i];
n = strlenChar(azData[i]);
utf8_printf(p->out, "%*s%s%*s%s",
(w-n)/2, "", azData[i], (w-n+1)/2, "",
i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
}
print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
break;
}
}
for(i=nColumn, j=0; i<nTotal; i++, j++){
if( j==0 && p->cMode!=MODE_Column ){
utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
}
z = azData[i];
if( z==0 ) z = p->nullValue;
w = p->actualWidth[j];
if( p->colWidth[j]<0 ) w = -w;
utf8_width_print(p->out, w, z);
if( j==nColumn-1 ){
utf8_printf(p->out, "%s", rowSep);
j = -1;
}else{
utf8_printf(p->out, "%s", colSep);
}
}
if( p->cMode==MODE_Table ){
print_row_separator(p, nColumn, "+");
}else if( p->cMode==MODE_Box ){
print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
}
sqlite3_free_table(azData);
}
/*
** Run a prepared statement
*/
@@ -2899,6 +3171,15 @@ static void exec_prepared_stmt(
){
int rc;
if( pArg->cMode==MODE_Column
|| pArg->cMode==MODE_Table
|| pArg->cMode==MODE_Box
|| pArg->cMode==MODE_Markdown
){
exec_prepared_stmt_columnar(pArg, pStmt);
return;
}
/* perform the first step. this will tell us if we
** have a result set or not and how wide it is.
*/
@@ -2946,6 +3227,9 @@ static void exec_prepared_stmt(
}
} while( SQLITE_ROW == rc );
sqlite3_free(pData);
if( pArg->cMode==MODE_Json ){
fputs("]\n", pArg->out);
}
}
}
}
@@ -3626,16 +3910,20 @@ static const char *(azHelp[]) = {
".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
".mode MODE ?TABLE? Set output mode",
" MODE is one of:",
" ascii Columns/rows delimited by 0x1F and 0x1E",
" csv Comma-separated values",
" column Left-aligned columns. (See .width)",
" html HTML <table> code",
" insert SQL insert statements for TABLE",
" line One value per line",
" list Values delimited by \"|\"",
" quote Escape answers as for SQL",
" tabs Tab-separated values",
" tcl TCL list elements",
" ascii Columns/rows delimited by 0x1F and 0x1E",
" box Tables using unicode box-drawing characters",
" csv Comma-separated values",
" column Output in columns. (See .width)",
" html HTML <table> code",
" insert SQL insert statements for TABLE",
" json Results in a JSON array",
" line One value per line",
" list Values delimited by \"|\"",
" markdown Markdown table format",
" quote Escape answers as for SQL",
" table ASCII-art table",
" tabs Tab-separated values",
" tcl TCL list elements",
".nullvalue STRING Use STRING in place of NULL values",
".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
" If FILE begins with '|' then open as a pipe",
@@ -3643,7 +3931,7 @@ static const char *(azHelp[]) = {
" -e Send output to the system text editor",
" -x Send output as CSV to a spreadsheet (same as \".excel\")",
#ifdef SQLITE_DEBUG
".oom [--repeat M] [N] Simulate an OOM error on the N-th allocation",
".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation",
#endif
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
" Options:",
@@ -3760,7 +4048,7 @@ static const char *(azHelp[]) = {
".vfsinfo ?AUX? Information about the top-level VFS",
".vfslist List all available VFSes",
".vfsname ?AUX? Print the name of the VFS stack",
".width NUM1 NUM2 ... Set column widths for \"column\" mode",
".width NUM1 NUM2 ... Set minimum column widths for columnar output",
" Negative values right-justify",
};
@@ -4597,6 +4885,7 @@ typedef struct ImportCtx ImportCtx;
struct ImportCtx {
const char *zFile; /* Name of the input file */
FILE *in; /* Read the CSV text from this input stream */
int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
char *z; /* Accumulated text for a field */
int n; /* Number of bytes in z */
int nAlloc; /* Space allocated for z[] */
@@ -4609,6 +4898,16 @@ struct ImportCtx {
int cRowSep; /* The row separator character. (Usually "\n") */
};
/* Clean up resourced used by an ImportCtx */
static void import_cleanup(ImportCtx *p){
if( p->in!=0 && p->xCloser!=0 ){
p->xCloser(p->in);
p->in = 0;
}
sqlite3_free(p->z);
p->z = 0;
}
/* Append a single byte to z[] */
static void import_append_char(ImportCtx *p, int c){
if( p->n+1>=p->nAlloc ){
@@ -7330,6 +7629,7 @@ static int do_meta_command(char *zLine, ShellState *p){
raw_printf(stderr, "The --preserve-rowids option is not compatible"
" with SQLITE_OMIT_VIRTUALTABLE\n");
rc = 1;
sqlite3_free(zLike);
goto meta_command_exit;
#else
ShellSetFlag(p, SHFLG_PreserveRowid);
@@ -7341,6 +7641,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
rc = 1;
sqlite3_free(zLike);
goto meta_command_exit;
}
}else if( zLike ){
@@ -7669,6 +7970,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
if( nArg==2 ){
p->showHeader = booleanValue(azArg[1]);
p->shellFlgs |= SHFLG_HeaderSet;
}else{
raw_printf(stderr, "Usage: .headers on|off\n");
rc = 1;
@@ -7698,7 +8000,6 @@ static int do_meta_command(char *zLine, ShellState *p){
char *zSql; /* An SQL statement */
ImportCtx sCtx; /* Reader context */
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
int eVerbose = 0; /* Larger for more console output */
int nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
@@ -7804,11 +8105,11 @@ static int do_meta_command(char *zLine, ShellState *p){
#else
sCtx.in = popen(sCtx.zFile+1, "r");
sCtx.zFile = "<pipe>";
xCloser = pclose;
sCtx.xCloser = pclose;
#endif
}else{
sCtx.in = fopen(sCtx.zFile, "rb");
xCloser = fclose;
sCtx.xCloser = fclose;
}
if( sCtx.in==0 ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
@@ -7832,7 +8133,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
if( zSql==0 ){
xCloser(sCtx.in);
import_cleanup(&sCtx);
shell_out_of_memory();
}
nByte = strlen30(zSql);
@@ -7848,8 +8149,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
if( cSep=='(' ){
sqlite3_free(zCreate);
sqlite3_free(sCtx.z);
xCloser(sCtx.in);
import_cleanup(&sCtx);
utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
rc = 1;
goto meta_command_exit;
@@ -7863,8 +8163,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( rc ){
utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
sqlite3_errmsg(p->db));
sqlite3_free(sCtx.z);
xCloser(sCtx.in);
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
}
@@ -7874,7 +8173,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( rc ){
if (pStmt) sqlite3_finalize(pStmt);
utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
xCloser(sCtx.in);
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
}
@@ -7884,7 +8183,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( nCol==0 ) return 0; /* no columns, no error */
zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
if( zSql==0 ){
xCloser(sCtx.in);
import_cleanup(&sCtx);
shell_out_of_memory();
}
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
@@ -7903,7 +8202,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( rc ){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
if (pStmt) sqlite3_finalize(pStmt);
xCloser(sCtx.in);
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
}
@@ -7955,8 +8254,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}while( sCtx.cTerm!=EOF );
xCloser(sCtx.in);
sqlite3_free(sCtx.z);
import_cleanup(&sCtx);
sqlite3_finalize(pStmt);
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
if( eVerbose>0 ){
@@ -8195,6 +8493,9 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
p->mode = MODE_Column;
if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
p->showHeader = 1;
}
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
p->mode = MODE_List;
@@ -8218,15 +8519,26 @@ static int do_meta_command(char *zLine, ShellState *p){
set_table_name(p, nArg>=3 ? azArg[2] : "table");
}else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
p->mode = MODE_Quote;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
p->mode = MODE_Ascii;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
}else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
p->mode = MODE_Markdown;
}else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
p->mode = MODE_Table;
}else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
p->mode = MODE_Box;
}else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
p->mode = MODE_Json;
}else if( nArg==1 ){
raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
}else{
raw_printf(stderr, "Error: mode should be one of: "
"ascii column csv html insert line list quote tabs tcl\n");
"ascii box column csv html insert json line list markdown "
"quote table tabs tcl\n");
rc = 1;
}
p->cMode = p->mode;
@@ -9327,7 +9639,7 @@ static int do_meta_command(char *zLine, ShellState *p){
raw_printf(p->out, "\n");
utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
utf8_printf(p->out, "%12.12s: ", "width");
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
for (i=0;i<p->nWidth;i++) {
raw_printf(p->out, "%d ", p->colWidth[i]);
}
raw_printf(p->out, "\n");
@@ -9876,7 +10188,11 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
int j;
assert( nArg<=ArraySize(azArg) );
for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
p->nWidth = nArg-1;
p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2);
if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
for(j=1; j<nArg; j++){
p->colWidth[j-1] = (int)integerValue(azArg[j]);
}
}else
@@ -10221,6 +10537,7 @@ static const char zOptions[] =
" -ascii set output mode to 'ascii'\n"
" -bail stop after hitting an error\n"
" -batch force batch I/O\n"
" -box set output mode to 'box'\n"
" -column set output mode to 'column'\n"
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
" -csv set output mode to 'csv'\n"
@@ -10236,9 +10553,11 @@ static const char zOptions[] =
" -help show this message\n"
" -html set output mode to HTML\n"
" -interactive force interactive I/O\n"
" -json set output mode to 'json'\n"
" -line set output mode to 'line'\n"
" -list set output mode to 'list'\n"
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
" -markdown set output mode to 'markdown'\n"
#if defined(SQLITE_ENABLE_DESERIALIZE)
" -maxsize N maximum size for a --deserialize database\n"
#endif
@@ -10258,6 +10577,7 @@ static const char zOptions[] =
" -sorterref SIZE sorter references threshold size\n"
#endif
" -stats print memory stats before each finalize\n"
" -table set output mode to 'table'\n"
" -version show SQLite version\n"
" -vfs NAME use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
@@ -10659,6 +10979,14 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
data.mode = MODE_Line;
}else if( strcmp(z,"-column")==0 ){
data.mode = MODE_Column;
}else if( strcmp(z,"-json")==0 ){
data.mode = MODE_Json;
}else if( strcmp(z,"-markdown")==0 ){
data.mode = MODE_Markdown;
}else if( strcmp(z,"-table")==0 ){
data.mode = MODE_Table;
}else if( strcmp(z,"-box")==0 ){
data.mode = MODE_Box;
}else if( strcmp(z,"-csv")==0 ){
data.mode = MODE_Csv;
memcpy(data.colSeparator,",",2);
@@ -10876,6 +11204,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
for(i=0; i<argcToFree; i++) free(argvToFree[i]);
free(argvToFree);
#endif
free(data.colWidth);
/* Clear the global data structure so that valgrind will detect memory
** leaks */
memset(&data, 0, sizeof(data));
+22 -8
View File
@@ -190,10 +190,10 @@
** WAL mode depends on atomic aligned 32-bit loads and stores in a few
** places. The following macros try to make this explicit.
*/
#ifndef __has_feature
# define __has_feature(x) 0 /* compatibility with non-clang compilers */
#ifndef __has_extension
# define __has_extension(x) 0 /* compatibility with non-clang compilers */
#endif
#if GCC_VERSION>=4007000 || __has_feature(c_atomic)
#if GCC_VERSION>=4007000 || __has_extension(c_atomic)
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
#else
@@ -2486,7 +2486,7 @@ struct Token {
** code for a SELECT that contains aggregate functions.
**
** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
** pointer to this structure. The Expr.iColumn field is the index in
** pointer to this structure. The Expr.iAgg field is the index in
** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
** code for that node.
**
@@ -2506,11 +2506,11 @@ struct AggInfo {
ExprList *pGroupBy; /* The group by clause */
struct AggInfo_col { /* For each column used in source tables */
Table *pTab; /* Source table */
int iTable; /* Cursor number of the source table */
int iColumn; /* Column number within the source table */
int iSorterColumn; /* Column number in the sorting index */
int iMem; /* Memory location that acts as accumulator */
Expr *pExpr; /* The original expression */
int iTable; /* Cursor number of the source table */
int iMem; /* Memory location that acts as accumulator */
i16 iColumn; /* Column number within the source table */
i16 iSorterColumn; /* Column number in the sorting index */
} *aCol;
int nColumn; /* Number of used entries in aCol[] */
int nAccumulator; /* Number of columns that show through to the output.
@@ -2523,8 +2523,17 @@ struct AggInfo {
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
#ifdef SQLITE_DEBUG
int iAggMagic; /* Magic number when valid */
#endif
AggInfo *pNext; /* Next in list of them all */
};
/*
** Value for AggInfo.iAggMagic when the structure is valid
*/
#define AggInfoMagic 0x2059e99e
/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater
@@ -3321,6 +3330,7 @@ struct Parse {
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
Parse *pParentParse; /* Parent parser if this parser is nested */
AggInfo *pAggList; /* List of all AggInfo objects */
int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
@@ -3725,6 +3735,9 @@ int sqlite3WalkSelectFrom(Walker*, Select*);
int sqlite3ExprWalkNoop(Walker*, Expr*);
int sqlite3SelectWalkNoop(Walker*, Select*);
int sqlite3SelectWalkFail(Walker*, Select*);
int sqlite3WalkerDepthIncrease(Walker*,Select*);
void sqlite3WalkerDepthDecrease(Walker*,Select*);
#ifdef SQLITE_DEBUG
void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif
@@ -4284,6 +4297,7 @@ int sqlite3ExprCompareSkip(Expr*, Expr*, int);
int sqlite3ExprListCompare(ExprList*, ExprList*, int);
int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
int sqlite3ExprImpliesNonNullRow(Expr*,int);
void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*);
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
+4 -3
View File
@@ -582,8 +582,9 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
#endif
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s",
pExpr->op2, pExpr->u.zToken, zFlgs);
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s iAgg=%d agg=%p",
pExpr->op2, pExpr->u.zToken, zFlgs,
pExpr->iAgg, pExpr->pAggInfo);
}else if( pExpr->op2!=0 ){
const char *zOp2;
char zBuf[8];
@@ -615,7 +616,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
break;
}
case TK_SELECT: {
sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
+2 -2
View File
@@ -342,9 +342,9 @@ SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
*z = 0;
assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
c = pMem->flags;
c = MEM_Str|MEM_Term|(pMem->flags&(MEM_AffMask|MEM_Subtype));
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype));
pMem->flags = c;
pMem->enc = desiredEnc;
pMem->z = (char*)zOut;
pMem->zMalloc = pMem->z;
+3 -3
View File
@@ -702,6 +702,8 @@ int sqlite3VdbeExec(
goto no_mem;
}
assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
testcase( p->rc!=SQLITE_OK );
p->rc = SQLITE_OK;
assert( p->bIsReader || p->readOnly!=0 );
p->iCurrentTime = 0;
assert( p->explain==0 );
@@ -8015,8 +8017,6 @@ no_mem:
*/
abort_due_to_interrupt:
assert( AtomicLoad(&db->u1.isInterrupted) );
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
p->rc = rc;
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
rc = SQLITE_INTERRUPT;
goto abort_due_to_error;
}
+9 -3
View File
@@ -3302,7 +3302,11 @@ int sqlite3VdbeReset(Vdbe *p){
*/
if( p->pc>=0 ){
vdbeInvokeSqllog(p);
sqlite3VdbeTransferError(p);
if( db->pErr || p->zErrMsg ){
sqlite3VdbeTransferError(p);
}else{
db->errCode = p->rc;
}
if( p->runOnlyOnce ) p->expired = 1;
}else if( p->rc && p->expired ){
/* The expired flag was set on the VDBE before the first call
@@ -3322,8 +3326,10 @@ int sqlite3VdbeReset(Vdbe *p){
for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
}
#endif
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
if( p->zErrMsg ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}
p->pResultSet = 0;
#ifdef SQLITE_DEBUG
p->nWrite = 0;
+5 -3
View File
@@ -1096,7 +1096,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
}
sLoc.aPgno[idx] = iPage;
sLoc.aHash[iKey] = (ht_slot)idx;
AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the number of entries in the hash table exactly equals
@@ -2846,12 +2846,14 @@ int sqlite3WalSnapshotRecover(Wal *pWal){
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
int rc; /* Return code */
int cnt = 0; /* Number of TryBeginRead attempts */
#ifdef SQLITE_ENABLE_SNAPSHOT
int bChanged = 0;
WalIndexHdr *pSnapshot = pWal->pSnapshot;
#endif
assert( pWal->ckptLock==0 );
#ifdef SQLITE_ENABLE_SNAPSHOT
int bChanged = 0;
WalIndexHdr *pSnapshot = pWal->pSnapshot;
if( pSnapshot ){
if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
bChanged = 1;
+37
View File
@@ -207,3 +207,40 @@ int sqlite3WalkSelect(Walker *pWalker, Select *p){
}while( p!=0 );
return WRC_Continue;
}
/* Increase the walkerDepth when entering a subquery, and
** descrease when leaving the subquery.
*/
int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){
UNUSED_PARAMETER(pSelect);
pWalker->walkerDepth++;
return WRC_Continue;
}
void sqlite3WalkerDepthDecrease(Walker *pWalker, Select *pSelect){
UNUSED_PARAMETER(pSelect);
pWalker->walkerDepth--;
}
/*
** No-op routine for the parse-tree walker.
**
** When this routine is the Walker.xExprCallback then expression trees
** are walked without any actions being taken at each node. Presumably,
** when this routine is used for Walker.xExprCallback then
** Walker.xSelectCallback is set to do something useful for every
** subquery in the parser tree.
*/
int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
return WRC_Continue;
}
/*
** No-op routine for the parse-tree walker for SELECT statements.
** subquery in the parser tree.
*/
int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
return WRC_Continue;
}
+2
View File
@@ -3028,6 +3028,7 @@ static int whereLoopAddBtree(
pNew->nOut = rSize;
pNew->u.btree.pIndex = pProbe;
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
/* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 );
if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
@@ -3057,6 +3058,7 @@ static int whereLoopAddBtree(
if( b
|| !HasRowid(pTab)
|| pProbe->pPartIdxWhere!=0
|| pSrc->fg.isIndexedBy
|| ( m==0
&& pProbe->bUnordered==0
&& (pProbe->szIdxRow<pTab->szTabRow)
+26
View File
@@ -916,6 +916,23 @@ static ExprList *exprListAppendList(
return pList;
}
/*
** When rewriting a query, if the new subquery in the FROM clause
** contains TK_AGG_FUNCTION nodes that refer to an outer query,
** then we have to increase the Expr->op2 values of those nodes
** due to the extra subquery layer that was added.
**
** See also the incrAggDepth() routine in resolve.c
*/
static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_AGG_FUNCTION
&& pExpr->op2>=pWalker->walkerDepth
){
pExpr->op2++;
}
return WRC_Continue;
}
/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it
@@ -939,12 +956,16 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
Window *pMWin = p->pWin; /* Master window object */
Window *pWin; /* Window object iterator */
Table *pTab;
Walker w;
u32 selFlags = p->selFlags;
pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ){
return sqlite3ErrorToParser(db, SQLITE_NOMEM);
}
sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlite3WalkSelect(&w, p);
p->pSrc = 0;
p->pWhere = 0;
@@ -1040,6 +1061,11 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
pTab->tabFlags |= TF_Ephemeral;
p->pSrc->a[0].pTab = pTab;
pTab = pTab2;
memset(&w, 0, sizeof(w));
w.xExprCallback = sqlite3WindowExtraAggFuncDepth;
w.xSelectCallback = sqlite3WalkerDepthIncrease;
w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
sqlite3WalkSelect(&w, pSub);
}
}else{
sqlite3SelectDelete(db, pSub);
+2 -2
View File
@@ -230,10 +230,10 @@ do_test 9.2 {
set L [list a=? b=? c=? d=? e=? f=? g=? h=? i=? j=?]
foreach {tn nTerm nRow} {
1 1 10
2 2 9
2 2 10
3 3 8
4 4 7
5 5 6
5 5 7
6 6 5
7 7 5
8 8 5
BIN
View File
Binary file not shown.
+12
View File
@@ -339,5 +339,17 @@ do_execsql_test index7-7.1 {
SELECT * FROM t6 WHERE y IS TRUE ORDER BY x;
} {1 1}
# 2020-05-27. tag-20200527-1.
# Incomplete stat1 information on a table with few rows should still use the
# index.
reset_db
do_execsql_test index7-8.1 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
CREATE INDEX t1y ON t1(y) WHERE y IS NOT NULL;
INSERT INTO t1(x) VALUES(1),(2);
ANALYZE;
EXPLAIN QUERY PLAN SELECT 1 FROM t1 WHERE y=5;
} {/SEARCH TABLE t1 USING COVERING INDEX t1y/}
finish_test
+13 -13
View File
@@ -95,7 +95,7 @@ do_test indexedby-2.4 {
# an error.
do_test indexedby-2.4.1 {
catchsql { SELECT b FROM t1 INDEXED BY i1 WHERE b = 'two' }
} {1 {no query solution}}
} {0 {}}
do_test indexedby-2.5 {
catchsql { SELECT * FROM t1 INDEXED BY i5 WHERE a = 'one' AND b = 'two'}
@@ -135,10 +135,10 @@ do_eqp_test indexedby-3.3 {
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
do_test indexedby-3.4 {
catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' }
} {1 {no query solution}}
} {0 {}}
do_test indexedby-3.5 {
catchsql { SELECT * FROM t1 INDEXED BY i2 ORDER BY a }
} {1 {no query solution}}
} {0 {}}
do_test indexedby-3.6 {
catchsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' }
} {0 {}}
@@ -154,7 +154,7 @@ do_eqp_test indexedby-3.9 {
} {SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}
do_test indexedby-3.10 {
catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 }
} {1 {no query solution}}
} {0 {}}
do_test indexedby-3.11 {
catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_2 WHERE f = 10 }
} {1 {no such index: sqlite_autoindex_t3_2}}
@@ -172,19 +172,19 @@ do_eqp_test indexedby-4.2 {
SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c
} {
QUERY PLAN
|--SCAN TABLE t2
`--SEARCH TABLE t1 USING INDEX i1 (a=?)
|--SCAN TABLE t1 USING INDEX i1
`--SEARCH TABLE t2 USING INDEX i3 (c=?)
}
do_test indexedby-4.3 {
catchsql {
SELECT * FROM t1 INDEXED BY i1, t2 INDEXED BY i3 WHERE a=c
}
} {1 {no query solution}}
} {0 {}}
do_test indexedby-4.4 {
catchsql {
SELECT * FROM t2 INDEXED BY i3, t1 INDEXED BY i1 WHERE a=c
}
} {1 {no query solution}}
} {0 {}}
# Test embedding an INDEXED BY in a CREATE VIEW statement. This block
# also tests that nothing bad happens if an index refered to by
@@ -205,7 +205,7 @@ do_test indexedby-5.4 {
# Recreate index i1 in such a way as it cannot be used by the view query.
execsql { CREATE INDEX i1 ON t1(b) }
catchsql { SELECT * FROM v2 }
} {1 {no query solution}}
} {0 {}}
do_test indexedby-5.5 {
# Drop and recreate index i1 again. This time, create it so that it can
# be used by the query.
@@ -245,7 +245,7 @@ do_eqp_test indexedby-7.5 {
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
do_test indexedby-7.6 {
catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5}
} {1 {no query solution}}
} {0 {}}
# Test that "INDEXED BY" can be used in an UPDATE statement.
#
@@ -266,7 +266,7 @@ do_eqp_test indexedby-8.5 {
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
do_test indexedby-8.6 {
catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5}
} {1 {no query solution}}
} {0 {}}
# Test that bug #3560 is fixed.
#
@@ -284,10 +284,10 @@ do_test indexedby-9.2 {
joinme as j indexed by joinme_id_text_idx
on ( m.id = j.id_int)
}
} {1 {no query solution}}
} {0 {}}
do_test indexedby-9.3 {
catchsql { select * from maintable, joinme INDEXED by joinme_id_text_idx }
} {1 {no query solution}}
} {0 {}}
# Make sure we can still create tables, indices, and columns whose name
# is "indexed".
+6
View File
@@ -171,6 +171,12 @@ test_suite "veryquick" -prefix "" -description {
*fts5corrupt* *fts5big* *fts5aj*
]
test_suite "shell" -prefix "" -description {
Run tests of the command-line shell
} -files [
test_set [glob $testdir/shell*.test]
]
test_suite "extraquick" -prefix "" -description {
"Extra" quick test suite. Runs in a few minutes on a workstation.
This test suite is the same as the "veryquick" tests, except that
+7
View File
@@ -3777,4 +3777,11 @@ foreach ::iRepeat {0 1} {
}
}
# 2020-05-23
# ticket 23439ea582241138
#
do_execsql_test printf-16.1 {
SELECT printf('%.*g',2147483647,0.01);
} {0.01}
finish_test
+8 -8
View File
@@ -199,10 +199,10 @@ do_test shell1-2.2.4 {
} {0 {}}
do_test shell1-2.2.5 {
catchcmd "test.db" ".mode \"insert FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
do_test shell1-2.2.6 {
catchcmd "test.db" ".mode \'insert FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
# check multiple tokens, and quoted tokens
do_test shell1-2.3.1 {
@@ -230,7 +230,7 @@ do_test shell1-2.3.7 {
# check quoted args are unquoted
do_test shell1-2.4.1 {
catchcmd "test.db" ".mode FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
do_test shell1-2.4.2 {
catchcmd "test.db" ".mode csv"
} {0 {}}
@@ -430,7 +430,7 @@ do_test shell1-3.13.1 {
} {0 {current output mode: list}}
do_test shell1-3.13.2 {
catchcmd "test.db" ".mode FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
do_test shell1-3.13.3 {
catchcmd "test.db" ".mode csv"
} {0 {}}
@@ -463,10 +463,10 @@ do_test shell1-3.13.11 {
# don't allow partial mode type matches
do_test shell1-3.13.12 {
catchcmd "test.db" ".mode l"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
do_test shell1-3.13.13 {
catchcmd "test.db" ".mode li"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
do_test shell1-3.13.14 {
catchcmd "test.db" ".mode lin"
} {0 {}}
@@ -709,11 +709,11 @@ do_test shell1-3.26.4 {
# this should be treated the same as a '1' width for col 1 and 2
} {0 {}}
do_test shell1-3.26.5 {
catchcmd "test.db" ".mode column\n.width 10 -10\nSELECT 'abcdefg', 123456;"
catchcmd "test.db" ".mode column\n.header off\n.width 10 -10\nSELECT 'abcdefg', 123456;"
# this should be treated the same as a '1' width for col 1 and 2
} {0 {abcdefg 123456}}
do_test shell1-3.26.6 {
catchcmd "test.db" ".mode column\n.width -10 10\nSELECT 'abcdefg', 123456;"
catchcmd "test.db" ".mode column\n.header off\n.width -10 10\nSELECT 'abcdefg', 123456;"
# this should be treated the same as a '1' width for col 1 and 2
} {0 { abcdefg 123456 }}
+7 -7
View File
@@ -426,7 +426,7 @@ do_test where9-4.5 {
AND (c=31031 OR d IS NULL)
ORDER BY +a
}
} {1 {no query solution}}
} {0 {92 93 97}}
do_test where9-4.6 {
count_steps {
SELECT a FROM t1 NOT INDEXED
@@ -442,7 +442,7 @@ do_test where9-4.7 {
AND (c=31031 OR d IS NULL)
ORDER BY +a
}
} {1 {no query solution}}
} {0 {92 93 97}}
do_test where9-4.8 {
catchsql {
SELECT a FROM t1 INDEXED BY t1d
@@ -450,7 +450,7 @@ do_test where9-4.8 {
AND (c=31031 OR d IS NULL)
ORDER BY +a
}
} {1 {no query solution}}
} {0 {92 93 97}}
# The (c=31031 OR d IS NULL) clause is preferred over b>1000 because
# the former is an equality test which is expected to return fewer rows.
@@ -776,7 +776,7 @@ do_test where9-6.8.1 {
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
}
} {1 {no query solution}}
} {0 {}}
do_test where9-6.8.2 {
catchsql {
UPDATE t1 INDEXED BY t1b SET a=a+100
@@ -784,7 +784,7 @@ do_test where9-6.8.2 {
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
}
} {1 {no query solution}}
} {0 {}}
set solution_possible 0
ifcapable stat4 {
@@ -818,7 +818,7 @@ if $solution_possible {
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
}
} {1 {no query solution}}
} {0 {}}
do_test where9-6.8.4 {
catchsql {
DELETE FROM t1 INDEXED BY t1b
@@ -826,7 +826,7 @@ if $solution_possible {
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
}
} {1 {no query solution}}
} {0 {}}
}
############################################################################
# Test cases where terms inside an OR series are combined with AND terms
+161
View File
@@ -1727,5 +1727,166 @@ do_execsql_test 52.4 {
4 938 938 4
}
# 2020-05-23
# ticket 7a5279a25c57adf1
#
reset_db
do_execsql_test 53.0 {
CREATE TABLE a(c UNIQUE);
INSERT INTO a VALUES(4),(0),(9),(-9);
SELECT a.c
FROM a
JOIN a AS b ON a.c=4
JOIN a AS e ON a.c=e.c
WHERE a.c=(SELECT (SELECT coalesce(lead(2) OVER(),0) + sum(d.c))
FROM a AS d
WHERE a.c);
} {4 4 4 4}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 54.1 {
CREATE TABLE t1(a VARCHAR(20), b FLOAT);
INSERT INTO t1 VALUES('1',10.0);
}
do_catchsql_test 54.2 {
SELECT * FROM (
SELECT sum(b) OVER() AS c FROM t1
UNION
SELECT b AS c FROM t1
) WHERE c>10;
} {1 {misuse of window function sum()}}
do_execsql_test 54.3 {
INSERT INTO t1 VALUES('2',5.0);
INSERT INTO t1 VALUES('3',15.0);
}
do_catchsql_test 54.4 {
SELECT * FROM (
SELECT sum(b) OVER() AS c FROM t1
UNION
SELECT b AS c FROM t1
) WHERE c>10;
} {1 {misuse of window function sum()}}
# 2020-06-05 ticket c8d3b9f0a750a529
reset_db
do_execsql_test 55.1 {
CREATE TABLE a(b);
SELECT
(SELECT b FROM a
GROUP BY b
HAVING (SELECT COUNT()OVER() + lead(b)OVER(ORDER BY SUM(DISTINCT b) + b))
)
FROM a
UNION
SELECT 99
ORDER BY 1;
} {99}
#------------------------------------------------------------------------
reset_db
do_execsql_test 56.1 {
CREATE TABLE t1(a, b INTEGER);
CREATE TABLE t2(c, d);
}
do_catchsql_test 56.2 {
SELECT avg(b) FROM t1
UNION ALL
SELECT min(c) OVER () FROM t2
ORDER BY nosuchcolumn;
} {1 {1st ORDER BY term does not match any column in the result set}}
reset_db
do_execsql_test 57.1 {
CREATE TABLE t4(a, b, c, d, e);
}
do_catchsql_test 57.2 {
SELECT b FROM t4
UNION
SELECT a FROM t4
ORDER BY (
SELECT sum(x) OVER() FROM (
SELECT c AS x FROM t4
UNION
SELECT d FROM t4
ORDER BY (SELECT e FROM t4)
)
);
} {1 {1st ORDER BY term does not match any column in the result set}}
# 2020-06-06 various dbsqlfuzz finds and
# ticket 0899cf62f597d7e7
#
reset_db
do_execsql_test 57.1 {
CREATE TABLE t1(a, b, c);
INSERT INTO t1 VALUES(NULL,NULL,NULL);
SELECT
sum(a),
min(b) OVER (),
count(c) OVER (ORDER BY b)
FROM t1;
} {{} {} 0}
do_execsql_test 57.2 {
CREATE TABLE v0 ( v1 INTEGER PRIMARY KEY ) ;
INSERT INTO v0 VALUES ( 10 ) ;
SELECT DISTINCT v1, lead(v1) OVER() FROM v0 GROUP BY v1 ORDER BY 2;
} {10 {}}
do_catchsql_test 57.3 {
DROP TABLE t1;
CREATE TABLE t1(a);
INSERT INTO t1(a) VALUES(22);
CREATE TABLE t3(y);
INSERT INTO t3(y) VALUES(5),(11),(-9);
SELECT (
SELECT max(y) OVER( ORDER BY (SELECT x FROM (SELECT sum(y) AS x FROM t1)))
)
FROM t3;
} {1 {misuse of aggregate: sum()}}
# 2020-06-06 ticket 1f6f353b684fc708
reset_db
do_execsql_test 58.1 {
CREATE TABLE a(a, b, c);
INSERT INTO a VALUES(1, 2, 3);
INSERT INTO a VALUES(4, 5, 6);
SELECT sum(345+b) OVER (ORDER BY b),
sum(avg(678)) OVER (ORDER BY c) FROM a;
} {347 678.0}
# 2020-06-06 ticket e5504e987e419fb0
do_catchsql_test 59.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(x INTEGER PRIMARY KEY);
INSERT INTO t1 VALUES (123);
SELECT
ntile( (SELECT sum(x)) ) OVER(ORDER BY x),
min(x) OVER(ORDER BY x)
FROM t1;
} {1 {misuse of aggregate: sum()}}
# 2020-06-07 ticket f7d890858f361402
do_execsql_test 60.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (x INTEGER PRIMARY KEY);
INSERT INTO t1 VALUES (99);
SELECT EXISTS(SELECT count(*) OVER() FROM t1 ORDER BY sum(x) OVER());
} {1}
# 2020-06-07 test case generated by dbsqlfuzz showing how an AggInfo
# object might be referenced after the sqlite3Select() call that created
# it returns. This proves the need to persist all AggInfo objects until
# the Parse object is destroyed.
#
reset_db
do_execsql_test 61.1 {
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(5),(NULL),('seventeen');
SELECT (SELECT max(x)OVER(ORDER BY x) % min(x)OVER(ORDER BY CASE x WHEN 889 THEN x WHEN x THEN x END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST((SELECT (SELECT max(x)OVER(ORDER BY x) / min(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN -true THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x) & sum ( a )OVER(ORDER BY CASE x WHEN -8 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a AS )) FROM t1) AS x FROM t1)) AS t1 )) FROM t1) AS x FROM t1)) AS x )) FROM t1) AS x FROM t1)) AS real)) FROM t1) AS x FROM t1);
} {{} {} {}}
finish_test