Compare commits

...

66 Commits

Author SHA1 Message Date
drh 5424075137 Put the affinity() function implementation inside of #ifdef SQLITE_DEBUG.
FossilOrigin-Name: f778f58ae4ea3e16f51b94591a2c1e563dcb0cde
2017-01-03 14:39:30 +00:00
drh 01e64a1704 Merge all the latest changes from trunk.
FossilOrigin-Name: c27cd8a8127b81d3176f6a5b9915c9b3c69574fb
2017-01-03 14:30:28 +00:00
drh 2710b14c45 Defer size checking on row-value assignments for when the RHS is a SELECT
until after the "*" wildcards have been expanded.

FossilOrigin-Name: 36944be6be5c42096f5da84187ff203af26b08ae
2017-01-03 13:45:22 +00:00
drh b67343d075 Fix a typo on a comment. No code changes.
FossilOrigin-Name: abc27b6023e28a717bfa15648ddc152bda9c7b96
2017-01-03 11:59:54 +00:00
dan f299edb0b0 Add test cases for the fix in [f12ed3ce]. No problems discovered.
FossilOrigin-Name: 548532fdcf84d565c17aed79a6b595e8b62a3ab4
2017-01-03 08:11:24 +00:00
drh 966e291160 Improvements to the way vector assignment size checking is done. Size checks
when the RHS is a SELECT are deferred until after "*" wildcards are expanded.

FossilOrigin-Name: 696219b11049930cdbc38f574820f4bbaf8621bb
2017-01-03 02:58:01 +00:00
drh 49cd39b48c Fix the row-values in UPDATE statements within TRIGGER problem identified
by ticket [8c9458e7].

FossilOrigin-Name: f12ed3ce0bfb2d94c9baad23fdcbd816c72439a1
2017-01-03 01:24:10 +00:00
drh b163748e88 Improved assert()s on the sqlite3ExprListDup() logic for TK_SELECT_COLUMN.
FossilOrigin-Name: 14da99d41f7968bf816203b4ae11c1f0d1ee0b5d
2017-01-03 00:27:16 +00:00
drh 90a7eae84c Test cases for the row-value UPDATE TRIGGER fix.
FossilOrigin-Name: b9b964373c89a491649f366ad7d70ae4d69b891d
2017-01-02 23:43:03 +00:00
drh 3f50bb84f5 Put an ALWAYS() on an unreachable branch in the sqlite3ExprListDup() routine.
FossilOrigin-Name: 2caaaab5e07f6b76d66fbe4e93a4b956937427d8
2017-01-02 23:18:35 +00:00
drh 47073f62bf Proposed fix for the row-value TRIGGER UPDATE problem described in
ticket [8c9458e7].

FossilOrigin-Name: 61a442ea2ceec2cbd327dae0ff5214e1f3c69ec0
2017-01-02 22:36:32 +00:00
drh 63a49ce0b2 Increase the version number to 3.17.0 for the next release cycle.
FossilOrigin-Name: 16415b5aad445c9e4e849018b48538d74eec8944
2017-01-02 19:10:14 +00:00
drh 56d65cd7b9 Provide the SQLITE_DEFAULT_LOOKASIDE compile-time option and make it's default
value be 1200,100 (raised from 512,125 in the latest release).

FossilOrigin-Name: 584da48f9e818f25134e0a62fb7e84f07019511f
2017-01-02 19:02:20 +00:00
drh 83a4f47d57 Change SQLITE_DEFAULT_PCACHE_INITSZ from 100 to 20, which is experimentally
determined to be slightly faster.

FossilOrigin-Name: 12d9493cb29307aec65ceccc68e802e4d0f18112
2017-01-02 18:40:03 +00:00
drh 38eef32172 Avoid unnecessary calls to sqlite3BtreeEnterAll() and sqlite3BtreeLeaveAll()
when no btree is using shared-cache.

FossilOrigin-Name: cfb3158204628eb2fd170090a7f212df0e4ce6c9
2017-01-02 18:19:29 +00:00
drh 197231b160 Add the --all option to the wordcount test program.
Fix the speedtest1 test program so that it builds on MSVC and so that
the --lookaside 0 0 option works.

FossilOrigin-Name: cb338f367e5408861bd7c0fbf74cebdbd8e3c515
2017-01-02 12:20:15 +00:00
drh e772bc7d30 Version 3.16.0
FossilOrigin-Name: 04ac0b75b1716541b2b97704f4809cb7ef19cccf
2017-01-02 11:57:58 +00:00
drh 245ce62ea2 Detect row-value comparison size mismatches even when the size of one
operand is obscured by an unexpanded subquery.

FossilOrigin-Name: 2c4d167ccd4be591487f404de9ee629fd484c8bf
2017-01-01 12:44:07 +00:00
drh e2b45d1789 Add the --help and --all options to the wordcount test utility.
FossilOrigin-Name: 18baeadfc89f6252e38dbc22904b11c5b56347ee
2016-12-31 21:55:23 +00:00
drh aa430bfb00 In speedtest1.c, make the "--lookaside 0 0" option completely disable lookaside.
FossilOrigin-Name: 52b99bcbf18f34196ec29f829c6af539e0d05524
2016-12-31 18:37:50 +00:00
drh eb25713e91 Minor #include change to speedtest1.c so that it will compile under MSVC.
FossilOrigin-Name: 8c28fde004678c85524770969eb001719b109179
2016-12-31 14:33:05 +00:00
dan 3043b53222 Fix a crash that could occur following an OOM in the group_concat() function
if the second argument is an SQLITE_BLOB value.

FossilOrigin-Name: 14d855d2b2b5b3485e0673d11405db7266b34c6d
2016-12-30 17:40:14 +00:00
drh 1d081ab39e Strengthen the defense against OOM in the instr() SQL function.
FossilOrigin-Name: a0971e713682a73d8c7c20511db256c20d2f6388
2016-12-30 15:16:20 +00:00
drh 5f4ade0473 Add a test to ensure that the app-defined pcache xFetch() method is never
passed a key of zero.

FossilOrigin-Name: 0bdbe49c6d392c4c86a6c01219c9d91d150dea7d
2016-12-30 14:25:42 +00:00
dan 895decf6b5 Avoid passing NULL pointers to memcmp() or memcpy(), even when the
"number-of-bytes" argument is passed 0.

FossilOrigin-Name: 56ff72ab44288296efc99a608f7edc4346366a50
2016-12-30 14:15:56 +00:00
drh d0d7e13511 Fix a harmless compiler warning in fuzzcheck.c
FossilOrigin-Name: 2842bc60538369f888c7df8365858c910322277d
2016-12-30 12:10:48 +00:00
drh 9c4dc22926 Disable the pagerAcquireMapPage() routine if memory-mapped I/O is disabled.
This fixes a harmless compiler warning on OpenBSD.

FossilOrigin-Name: 3e25ba6e42fba239795a465b8510386a361ee5be
2016-12-30 12:06:22 +00:00
drh fb4e3a3bbb Encode a 64-bit integer literal in date.c as a constant expression so that
it works on older compilers.  Also fix a harmless compiler warning in vdbe.c.

FossilOrigin-Name: f57952bac652901e1bd48b68301941efbcf29dc4
2016-12-30 00:09:14 +00:00
drh 96ada59cbb Fix harmless compiler warnings in the command-line shell and in Lemon.
FossilOrigin-Name: afcdc4a60e357d171156e0de705bf7ad1b37daab
2016-12-29 19:48:46 +00:00
drh cae20d5cf1 In kvtest.c, use stat() instead of fseek()/ftell() to determine the size of
a BLOB to be read directly from disk.  This makes the pile-of-files database
more competative against SQLite.

FossilOrigin-Name: a7dca29f03e037fe71cc600db97f8058e3bd28a4
2016-12-29 17:25:06 +00:00
drh 03d0c20bbd Add the kvtest.c test program used to show that it is many times faster to
read thumbnail and similar BLOBs out of an SQLite database than it is to read
them as separate files from the filesystem.

FossilOrigin-Name: 8074d59cf177cb91ee371e2660f2c59ce540b7e2
2016-12-29 16:58:01 +00:00
drh 2f917e05d7 Add more detail to the header command to further explain how to compile and
use the kvtest.c utility.

FossilOrigin-Name: 55d29839c9fafe9e6a694f5790151d1f22396b01
2016-12-29 16:49:22 +00:00
drh d7b9b97c3b Fix kvtest.c so that it compiles using MSVC.
FossilOrigin-Name: e2bbeae7e77cde531885ca492494a02e5322154d
2016-12-29 16:18:35 +00:00
drh 6739c692ba In kvtest.c: do not show the --cache-size setting on fopen() runs.
Show progress for the (potentially slow) "export" command.

FossilOrigin-Name: b0f58d2470e08b9c217afd19fcfde3e6d1007d1d
2016-12-29 15:26:50 +00:00
drh 61c565f63b Improvements to the kvtest.c utility. Added the --cache-size option.
Additional reporting of version and settings at the end of "./kvtest run".

FossilOrigin-Name: f6fcac6ae8b3bffee6bf994eef2064affd301a95
2016-12-29 14:44:43 +00:00
drh cac028ba19 Add the kvtest.c test program for measuring key/value read performance under
various scenarios.

FossilOrigin-Name: 489e0787c1ea47963174387e8ade6295ceff568e
2016-12-29 03:57:43 +00:00
drh 402124de5c Do not allow the nockpt.test module to run under the inmemory_journal
permutation.

FossilOrigin-Name: a6af06f164b1f65779e2171ec4946119c66f9be8
2016-12-27 15:59:15 +00:00
drh 575242f66f Allow sqlite3_interrupt() to be invoked on a database connection that is in
the process of being closed even if SQLITE_ENABLE_API_ARMOR is defined.

FossilOrigin-Name: 7854bee260996087bdb7f8729ba8cfb4f467f93f
2016-12-27 13:33:52 +00:00
drh 5ad74a761d Adjust a corruption test case to accommodate the sqlite3BtreeInsert()
optimization of check-in [0b86fbca66].

FossilOrigin-Name: 4cb0945f13f2040c8b67936b950da48fc951d55d
2016-12-27 12:45:41 +00:00
drh 218c66e0e3 Disable new test modules nockpt.test and interrupt2.test for incompatible
permutations.  Add a CORRUPT_DB term to an assert() in vdbe.c.

FossilOrigin-Name: a54e619e6f0266932c8873f9ac826fd042a0602f
2016-12-27 12:35:36 +00:00
drh 1aa346950e Avoid a potential (harmless) signed integer overflow in memory usage
accounting when calling sqlite3_realloc() to reduce the size of an
allocation.

FossilOrigin-Name: 2d71cbdf6bc24f0269027c70b39ea7f342436bdb
2016-12-27 12:08:36 +00:00
drh c595419910 Minor changes to make some newer test cases work under more compile-time
options.

FossilOrigin-Name: 382eea36c56f866efee1321f643687a4061e8b9e
2016-12-27 02:43:47 +00:00
drh dfcfff646a During fuzz testing with the fuzzcheck utility program, impose a record
length limit of 100MB and a limit on the length of LIKE strings of 50 bytes.

FossilOrigin-Name: edc9db41f3ee200ba44579a46ed8331bbbbf539e
2016-12-26 12:25:19 +00:00
drh e6ce2b6704 Enable ossfuzz.c to build even if SQLITE_OMIT_PROGRESS_CALLBACK is defined.
FossilOrigin-Name: a37c00dcd192f9d610ecb91810ef57ef41d1f6a6
2016-12-26 12:14:44 +00:00
drh 9cc5b4eeb5 Remove an incorrect ALWAYS() macro from balance_nonroot(), which could result
in corrupt databases if it were optimized out.  This ALWAYS was added 
only two weeks ago (check-in [f9f2e23bbd68a]) and has never appeared in an
official release.

FossilOrigin-Name: e447b23cfd7bb31817e42adb3a98868d351c6b8a
2016-12-26 01:41:33 +00:00
drh a1a523a5bb Add the built-in affinity() SQL function.
FossilOrigin-Name: 57e40e1cb1bcd3dd8473d2fdeecc9c7ff3d6192b
2016-12-26 00:18:36 +00:00
drh beaf514e23 Enhance the fuzztest utility with the --prng-seed option. Always reseed the
PRNG prior to each test.

FossilOrigin-Name: 8c5187f69d719b69aa6eaf2dc8f89243e5979222
2016-12-26 00:15:56 +00:00
drh 6a5a4208fc Combine the implementations of the ".tables" and ".indexes" commands in the
command-line shell.  The ".indexes" command now puts the indexes in multiple
columns, just like ".tables" and shows all indexes in all attached databases.

FossilOrigin-Name: def29333655691c7d54451193be13445a2857d29
2016-12-24 21:32:40 +00:00
drh 2951809ed4 The schema name "main" is always an acceptable alias for the primary database
even if the primary database is renamed using SQLITE_DBCONFIG_MAINDBNAME.

FossilOrigin-Name: 2f481b854f04bec546eb172d1b6dbc88067d3fda
2016-12-24 19:37:16 +00:00
drh b20a61b704 Change the output format of the ".databases" command in the command-line shell
so that it shows the schema name, a colon, and the corresponding filename.

FossilOrigin-Name: 8558512e9ca343300a767ef23810f2d7b50fd925
2016-12-24 18:18:58 +00:00
drh a4b81d2a44 In the command-line shell, improve the formatting to the ".databases"
command and on the ".tables" command, only show the schema prefix for
databases past the first ("main") database.

FossilOrigin-Name: c0d5626e274cbf8c2d2167183c4d6835d72dae57
2016-12-24 18:04:28 +00:00
drh 6bd4dc6dc4 Fill in missing opcode documentation entries for OP_SorterNext and
OP_SorterSort.

FossilOrigin-Name: 2940661b8c014b94973e05c44f1b1f4f443dbdd3
2016-12-23 16:05:22 +00:00
drh cfdc235ec3 Use the VList object to capture the mapping between SQL parameter names and
variable numbers in a single memory allocation.

FossilOrigin-Name: 99fddf2ecb7202bfdf5ddc4cc1c4e155c883f7ec
2016-12-23 13:54:22 +00:00
drh ce1bbe51b5 Add check to prevent a VList from growing after pointers to labels have been
taken.

FossilOrigin-Name: aa23d7eaf69f5ecbf9500b2353846094cae41e6c
2016-12-23 13:52:45 +00:00
drh f326d66d61 Fix the VList object so that it actually works.
FossilOrigin-Name: 9dcd85698af46fd5ba34004ca690d368c4ae3078
2016-12-23 13:30:53 +00:00
drh 9bf755cc44 Use the VList object to replace Parse.azVar for tracking the mapping between
SQL parameter names and parameter numbers.  There is a performance
improvement, though there are still a few hiccups in the current code.

FossilOrigin-Name: 68ecafa1425a41358c88f41efea3262f1b4490f2
2016-12-23 03:59:31 +00:00
drh 344a1bf133 Fix harmless compiler warnings.
FossilOrigin-Name: fa86db2f915c0a189c3be02b1aaa7f24d339d7d6
2016-12-22 14:53:25 +00:00
drh cdfffed790 Change the default lookaside configuration from 500 slots of 128 bytes each to 125 slots of 512 bytes each. This uses the same amount of memory (64,000 bytes) but seems to perform much better in test applications.
FossilOrigin-Name: 52a12e47de88744187bd1c71f2820885cde414a8
2016-12-21 21:26:58 +00:00
drh a582b01698 Simplifications to the way UnpackedRecord objects are allocated. Smaller
and faster code that also fixes a subtle (currently unreachable) bug.

FossilOrigin-Name: f7ab01f254cd9d7006b8dec29adb234a671b8e6f
2016-12-21 19:45:54 +00:00
drh f99dd359d0 Change the OP_IfNotZero opcode so that it decrements register P1 by 1 rather
than the value in P3, and so that it only decrements if originally positive.
This avoids decrementing the smallest 64-bit signed integer.

FossilOrigin-Name: 165c044686212fbf7182dd560ad1e57eb4cc9838
2016-12-18 17:42:00 +00:00
drh 22d709dd91 Refinements to the new dbfuzz test program.
FossilOrigin-Name: 50325abe79b6a79b09ec6a1cee7d80ca02337428
2016-12-17 21:07:30 +00:00
drh 6918e2f9b2 Enhance fuzzershell.c to read and execute SQL commands in the autoexec table
of the database under test.  Add the dbfuzz.c test program combining selected
features of fuzzershell.c and fuzzcheck.c.

FossilOrigin-Name: ef6e071a62cd79a0edbbef9f41ca9482540e5cb8
2016-12-17 20:27:22 +00:00
dan 11da002c02 Fix a problem in the shell tools readfile() command causing blobs to be
truncated at the first embedded 0x00 byte in release builds, or an assert() to
fail in a debug build.

FossilOrigin-Name: 8dedd6ad44bd1d103dced9d1350188cb2327128d
2016-12-17 08:18:05 +00:00
drh d47c6c495d Add the ".lint fkey-indexes" command to the command-line shell.
FossilOrigin-Name: 94689e3bdac2eabbcf1a51d741c2604ed4bd8a40
2016-12-16 18:43:49 +00:00
drh 186c930702 Built-in PRAGMA statements without side-effects can be invoked as
table-valued functions by prefixing their name with "pragma_".

FossilOrigin-Name: d66ec5cfb67c6c8134fb642e0c2f72113fe1b7fd
2016-12-16 18:14:19 +00:00
dan 69b9383edf Fix a problem causing the planner to generate sub-optimal plans for some queries
that use recursive WITH sub-queries with LIMIT clauses.

FossilOrigin-Name: 053a149cc8244a7f85137129cfcb8622efe90306
2016-12-16 15:05:40 +00:00
51 changed files with 2540 additions and 537 deletions
+4
View File
@@ -567,6 +567,7 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
DBFUZZ_OPT =
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
@@ -621,6 +622,9 @@ fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h
ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c sqlite3.c sqlite3.h $(TLIBS)
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \
$(TLIBS) -rpath "$(libdir)"
+1 -1
View File
@@ -1 +1 @@
3.16.0
3.17.0
Vendored
+10 -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.16.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.17.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.16.0'
PACKAGE_STRING='sqlite 3.16.0'
PACKAGE_VERSION='3.17.0'
PACKAGE_STRING='sqlite 3.17.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1463,7 +1463,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.16.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.17.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1528,7 +1528,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.16.0:";;
short | recursive ) echo "Configuration of sqlite 3.17.0:";;
esac
cat <<\_ACEOF
@@ -1652,7 +1652,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.16.0
sqlite configure 3.17.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2071,7 +2071,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.16.0, which was
It was created by sqlite $as_me 3.17.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12151,7 +12151,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.16.0, which was
This file was extended by sqlite $as_me 3.17.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12217,7 +12217,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.16.0
sqlite config.status 3.17.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -13829,3 +13829,4 @@ if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+7 -9
View File
@@ -374,9 +374,7 @@ static int sessionSerializeValue(
if( aBuf ){
sessionVarintPut(&aBuf[1], n);
memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ?
sqlite3_value_text(pValue) : sqlite3_value_blob(pValue), n
);
if( n ) memcpy(&aBuf[nVarint + 1], z, n);
}
nByte = 1 + nVarint + n;
@@ -1792,7 +1790,7 @@ static void sessionAppendBlob(
int nBlob,
int *pRc
){
if( 0==sessionBufferGrow(p, nBlob, pRc) ){
if( nBlob>0 && 0==sessionBufferGrow(p, nBlob, pRc) ){
memcpy(&p->aBuf[p->nBuf], aBlob, nBlob);
p->nBuf += nBlob;
}
@@ -1978,13 +1976,13 @@ static int sessionAppendUpdate(
}
default: {
int nByte;
int nHdr = 1 + sessionVarintGet(&pCsr[1], &nByte);
int n;
int nHdr = 1 + sessionVarintGet(&pCsr[1], &n);
assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
nAdvance = nHdr + nByte;
nAdvance = nHdr + n;
if( eType==sqlite3_column_type(pStmt, i)
&& nByte==sqlite3_column_bytes(pStmt, i)
&& 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), nByte)
&& n==sqlite3_column_bytes(pStmt, i)
&& (n==0 || 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), n))
){
break;
}
+6
View File
@@ -477,6 +477,7 @@ SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
DBFUZZ_OPT =
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
@@ -513,6 +514,11 @@ fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
$(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \
$(TLIBS) $(THREADLIB)
dbfuzz$(EXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
$(TCCX) -o dbfuzz$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c \
$(TLIBS) $(THREADLIB)
fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c
$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \
+54 -50
View File
@@ -1,10 +1,10 @@
C Fix\sminor\sissues\swith\sthe\s".lint"\scommand\simplemention\sin\sthe\sshell\sand\nthe\sshell\shelp\stext\srelated\sto\s".lint".
D 2016-12-16T18:41:11.376
F Makefile.in c194b58fe00c370a48ac6ae6945e92a7781db1c8
C Put\sthe\saffinity()\sfunction\simplementation\sinside\sof\s#ifdef\sSQLITE_DEBUG.
D 2017-01-03T14:39:30.860
F Makefile.in 41bd4cad981487345c4a84081074bcdb876e4b2e
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION 661b3e6a778cfbfd7bdce8bbb1545b22f4b6f09e
F VERSION cddd8d88dc8202afa0ebc96da61fc4acbd1e96a5
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -30,7 +30,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure adbf03e758431e886bba5ab04b5adfbd496d7b24 x
F configure fcfa56d5d66668c9263dc007724f62acff06dc83 x
F configure.ac 605173e829ab64514ed89f9b53d0da1739d7b0a0
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html b5a3c07d33ecb8e019ce8f7660fe2dbbad9d7977
@@ -303,7 +303,7 @@ F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
F ext/session/session_common.tcl 9b696a341cf1d3744823715ed92bb19749b6c3d4
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
F ext/session/sqlite3session.c 37485891b4add26cf61495df193c419f36556a32
F ext/session/sqlite3session.c c61a43396368ec00dc127f7bc647e9bd6a4ee5fb
F ext/session/sqlite3session.h 9345166bd8f80562145586cf817f707de5ecada2
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
@@ -312,7 +312,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk bd1149fdb5543e432a8530a0ea7642613a655bc1
F main.mk 2cf5f0362c5687fd8e912c3a327b49a2e8ba0f9b
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -325,27 +325,27 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
F src/analyze.c 8b62b2cf4da85451534ac0af82cafc418d837f68
F src/attach.c f6725410c184a80d8141b294fdf98a854c8a52b5
F src/analyze.c 3c4a63ff7a55faefecf6eb1589932fdbc06b2415
F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43
F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btree.c b2055dff0b94e03eaad48a760984a2d8e39244e6
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
F src/btree.c d2c100618784bd89c089fcef03ff6e789768ecae
F src/btree.h 2349a588abcd7e0c04f984e15c5c777b61637583
F src/btreeInt.h 10c4b77c2fb399580babbcc7cf652ac10dba796e
F src/build.c 52970b6cf3cf3107551a5d6dd668b0b261b0b491
F src/build.c 9e799f1edd910dfa8a0bc29bd390d35d310596af
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 9f2296a4e5d26ebf0e0d95a0af4628f1ea694e7a
F src/date.c b48378aeac68fa20c811404955a9b62108df47d8
F src/date.c dc3f1391d9297f8c748132813aaffcb117090d6e
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
F src/delete.c c8bc10d145c9666a34ae906250326fdaa8d58fa5
F src/expr.c c7c11fbe8bd4d27d04f1370efcce5a05b4fca229
F src/expr.c 449cbb8b9857ff8eb685b72555086818a178858c
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
F src/func.c 43916c1d8e6da5d107d91d2b212577d4f69a876a
F src/global.c 235021a21ee2cb52b304589f8f9e85a36bbe24fa
F src/func.c c67273e1ec08abbdcc14c189892a3ff6eeece86b
F src/global.c 4a34512d82fc5aa13c802db06bcfff5e1d3de955
F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
@@ -353,8 +353,8 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 91ba5d0143e66479081536ebbaff1850ec9f57d9
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
F src/loadext.c 5d6642d141c07d366e43d359e94ec9de47add41d
F src/main.c c0daeb1f716de3e93c573aeed6b164faeddee772
F src/malloc.c 5ee7c2d3dcb1b0a902c9c6d0115deef54736bdfa
F src/main.c e207b81542d13b9f13d61e78ca441f9781f055b0
F src/malloc.c f3fad34cd570022abca558c573f1761fb09a8212
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@@ -375,25 +375,25 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820
F src/os_win.c cf90abd4e50d9f56d2c20ce8e005aff55d7bd8e9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 81fe2bb847df537694ec39e28e8b3dc221c64a7d
F src/pager.c 9dc72d23eebbdf992bd69f2ab954d0d3a27c7340
F src/pager.h d1e944291030351f362a0a7da9b5c3e34e603e39
F src/parse.y 29153738a7322054359320eb00b5a4cd44389f20
F src/pcache.c 51070ec9b8251bbf9c6ea3d35fd96a458752929e
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
F src/pragma.c d5adfe89ad7f3f45d4dbd25b96cbf3f6611aea2a
F src/pragma.c 5a23557e490e7ac5afef097efc4b59dce5b482c2
F src/pragma.h f9b221b2c8949ea941dbee49934299e4ed5af41c
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c f94da4935d1dd25420ac50c6745db1deb35e07c1
F src/printf.c 0c8579432f47948d9be5077eb590e8c4a01be667
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c bb070cf5f23611c44ab7e4788803684e385fc3fb
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 204491a5e09a66380a067943d8651af8bda1d358
F src/shell.c 9be556ad9c7cf429d0acc48e386960d290c4df75
F src/select.c dfb6cadc3dcfba1b1bdbfba62ebba2b4b673413e
F src/shell.c 6095531aa900decdaa765e0f3993fba7153c92c1
F src/sqlite.h.in e8e2d108d82647f0a812fdb74accf91c1ec08ddc
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
F src/sqliteInt.h adbe80409c2926d91e5485789e5bf69313cd54b0
F src/sqliteInt.h 2c22eae7a29f17e0dfee9737d4844d7c08cc38cd
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
@@ -448,21 +448,21 @@ F src/test_windirent.c 600398db0198ca1c77ca183831bf456746b6f5c4
F src/test_windirent.h 7edc57e2faa727026dbd5d010dd0e2e665d5aa01
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 6eb0752c4fd191f789190c3708ee5b0060fd2829
F src/tokenize.c 5c2f516876fc27fbd7753913f032f49eb89e83b5
F src/treeview.c 4e44ade3bfe59d82005039f72e09333ce2b4162c
F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182
F src/update.c 1da7c462110bffed442a42884cb0d528c1db46d8
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c e68e8ced7328f22d2cf7b4c898c394a0de34cdf1
F src/util.c 1534060bc034cdc51381c040c8bd6252dbcb64c9
F src/vacuum.c 33c174b28886b2faf26e503b5a49a1c01a9b1c16
F src/vdbe.c 64c3426893e1660bde7446c242468926555e3650
F src/vdbe.h 0c74f6305fb43b9b282dacaff102272370e327d4
F src/vdbeInt.h 42e498dbe96475dbb3fda3d85d8fd2a87eff60a2
F src/vdbeapi.c ea4e2dc2213cc6bd7bee375a29a9b51c31b93ae0
F src/vdbeaux.c f5edc89007f8a49e224089a4a4dddbc11bd38213
F src/vdbe.c 88bd6c32b333580d2661ac3afe33369757fb1522
F src/vdbe.h 50ee139f9c68fff91be1d717ed3a6abbd496919c
F src/vdbeInt.h 281cb70332dc8b593b8c7afe776f3a2ba7d4255e
F src/vdbeapi.c d6ebaa465f070eb1af8ba4e7b34583ece87bdd24
F src/vdbeaux.c 12919c5aa354296d6b9ba808bca3e9dda836858c
F src/vdbeblob.c f4f98ea672b242f807c08c92c7faaa79e5091b65
F src/vdbemem.c d3fd85b7b7ef3eb75de29c6d7e1d10d3ca78b4fd
F src/vdbesort.c bb34eed4fb52e11ac037dccea4ee3190594c7f9e
F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
F src/vtab.c c4bbe0f870f52036553f8098aee0703997f0577a
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
@@ -600,7 +600,7 @@ F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
F test/corruptC.test 0c46574f8d4f27ecc799b1b5c4cbf9b1817bce9a
F test/corruptC.test 4ef10844eba5213bd262f4d96784d7fcda114afe
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
F test/corruptE.test 82ccf4f8f543fdbedd4aa42c709cb077f7374c62
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
@@ -628,6 +628,7 @@ F test/ctime.test ff6c38e822459d6ca743c34901caf57740b08b54
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test fa41f0d997e67db921d08c31e73111b32811201a
F test/date.test a6a5a48b90907bca9fbcc79a30be5a715c1ab2fc
F test/dbfuzz.c 8cc2bdb818b4483a052f9f80f96be74cbd9a6e1d
F test/dbstatus.test 73149851b3aff14fc6db478e58f9083a66422cf5
F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
@@ -815,7 +816,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test b47377143f0c80f91ed29d722861077ff34415d5
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzcheck.c 5592b19e07b9061833a35eaf78869ad0c8b6cf33
F test/fuzzcheck.c a87e6067a8d19844bade916841cb76150ecf24a2
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -824,6 +825,7 @@ F test/fuzzdata5.db 9f0cdcc5c6e83b90cf9ae343bd07f684d2da2de7
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
@@ -864,11 +866,11 @@ F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test a20432f1c0fbbcff8f11d0e6ab4acb8c9db58023
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2
F test/instrfault.test aa90b7c3486a069151b28384ae525644a1f79d51
F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba
F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a
F test/intarray.test 46d95b457916638c5d8b1af21fb174804b3acf8b
F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054
F test/interrupt2.test 829b06f9e20a6c378d8bd121b26c337f4dfa36e5
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8
F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc
F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d
@@ -893,6 +895,7 @@ F test/json101.test c0897616f32d95431f37fd291cb78742181980ac
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c 2c66ddefcd03c2caa337f6dd79e6c82368af83df
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/like.test 0603f4fa0dad50987f70032c05800cbfa8985302
@@ -966,7 +969,7 @@ F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test dacc57f80859c06a433d30839336fe227d2038b3
F test/nockpt.test c65fc1c921d48805dcfca2dca5d1302839a5a1de
F test/nockpt.test 9a436a7213ba5ef7a32304998d386d3ea3f76c9d
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
@@ -987,7 +990,7 @@ F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
F test/ossfuzz.c ad79e867fb504338d324b08e0696db65a0c44d68
F test/ossfuzz.c e469138f4be3e92df6173b79b3b216ab6e17b407
F test/ossshell.c d9f1a6f43e7bab45d6be857a5800f5d4a1861db3
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
F test/pager1.test 841868017e9dd3cb459b8d78862091a7d9cff21d
@@ -1032,7 +1035,7 @@ F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d
F test/rowvalue.test cacc565ed7e3ac467866af6705dd99020fdf2ee2
F test/rowvalue.test 44f3492f415cc9f374e8388a5eb61503eaca5230
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
F test/rowvalue4.test 4b556d7de161a0dd8cff095c336e913986398bea
@@ -1089,12 +1092,13 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 8ff47a4821570b99cc340c4da0ac4efe2ba06627
F test/shell1.test 52ac23a345772ab0d6d3241a21a633fdaa3ed581
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
F test/shell5.test 50a732c1c2158b1cd62cf53975ce1ea7ce6b9dc9
F test/shell6.test 806472f6ffdd31d632e27dbe8515c0c45f68f3ec
F test/shell6.test cff624fadf71bdb5e3a9b0f86eaf59a43c0622b1
F test/shell7.test 07751911b294698e0c5df67bcbd29e7d2f0f2907
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
@@ -1123,7 +1127,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 0c92fd0db4cb778e3b6968db0ea859e28f077823
F test/speedtest1.c 4e8ea6165046f02e1cfe0f4700256e91c981ec10
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1437,7 +1441,7 @@ F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/with1.test cef099a491eac9874f2c28bd2dc86394fb3e47b3
F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98
F test/with3.test e71604a0e53cba82bc04c703987cb1d6751ec0b6
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
@@ -1445,7 +1449,7 @@ F test/without_rowid3.test 2724c787a51a5dce09d078453a758117b4b728f1
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
F test/wordcount.c 97856eec21fd00d77da720007b1888c383f63dcf
F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
@@ -1460,11 +1464,11 @@ F tool/dbhash.c a06228aa21ebc4e6ea8daa486601d938499238a5
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/fuzzershell.c d5c870a07452caa5c70a8e49d6c64e403558686d
F tool/fuzzershell.c dbf6c26eef936ec78cb0707570de3a4308b2507e
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c e4fb7d888873ac88f20a41c84a7d1e61f5209a6d
F tool/lemon.c 5ccba178a8e8a4b21e1c9232944d23973da38ad7
F tool/lempar.c 320d630b44da693407684c64d9fa91a163419dac
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
@@ -1537,7 +1541,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 ee621ade38c11806e1df57c459da5f018a6d0670
R c295b60403c83c54dd0a041668d05312
P c27cd8a8127b81d3176f6a5b9915c9b3c69574fb
R 4de702ec2e06c17a2db8893398d4255a
U drh
Z 639f0a5a4b0a629c3f185644f89569f0
Z f4b6e6ab3f6bbd45ad65d1c563858923
+1 -1
View File
@@ -1 +1 @@
1268dc77712d85de0b62332c88b22f7489f4e87f
f778f58ae4ea3e16f51b94591a2c1e563dcb0cde
+3 -1
View File
@@ -1766,7 +1766,9 @@ static int loadStatTbl(
sqlite3_finalize(pStmt);
return SQLITE_NOMEM_BKPT;
}
memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
if( pSample->n ){
memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
}
pIdx->nSample++;
}
rc = sqlite3_finalize(pStmt);
+1
View File
@@ -137,6 +137,7 @@ static void attachFunc(
rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
sqlite3_free( zPath );
db->nDb++;
db->skipBtreeMutex = 0;
if( rc==SQLITE_CONSTRAINT ){
rc = SQLITE_ERROR;
zErrDyn = sqlite3MPrintf(db, "database is already attached");
+14 -3
View File
@@ -183,16 +183,24 @@ int sqlite3BtreeHoldsMutex(Btree *p){
** two or more btrees in common both try to lock all their btrees
** at the same instant.
*/
void sqlite3BtreeEnterAll(sqlite3 *db){
static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){
int i;
int skipOk = 1;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; i<db->nDb; i++){
p = db->aDb[i].pBt;
if( p ) sqlite3BtreeEnter(p);
if( p && p->sharable ){
sqlite3BtreeEnter(p);
skipOk = 0;
}
}
db->skipBtreeMutex = skipOk;
}
void sqlite3BtreeLeaveAll(sqlite3 *db){
void sqlite3BtreeEnterAll(sqlite3 *db){
if( db->skipBtreeMutex==0 ) btreeEnterAll(db);
}
static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){
int i;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
@@ -201,6 +209,9 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){
if( p ) sqlite3BtreeLeave(p);
}
}
void sqlite3BtreeLeaveAll(sqlite3 *db){
if( db->skipBtreeMutex==0 ) btreeLeaveAll(db);
}
#ifndef NDEBUG
/*
+7 -10
View File
@@ -763,26 +763,23 @@ static int btreeMoveto(
){
int rc; /* Status code */
UnpackedRecord *pIdxKey; /* Unpacked index key */
char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */
char *pFree = 0;
if( pKey ){
assert( nKey==(i64)(int)nKey );
pIdxKey = sqlite3VdbeAllocUnpackedRecord(
pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
);
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 ){
sqlite3DbFree(pCur->pKeyInfo->db, pFree);
return SQLITE_CORRUPT_BKPT;
rc = SQLITE_CORRUPT_BKPT;
goto moveto_done;
}
}else{
pIdxKey = 0;
}
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
if( pFree ){
sqlite3DbFree(pCur->pKeyInfo->db, pFree);
moveto_done:
if( pIdxKey ){
sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
}
return rc;
}
@@ -7080,7 +7077,7 @@ static int balance_nonroot(
nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
if( (i--)==0 ) break;
if( pParent->nOverflow && ALWAYS(i+nxDiv==pParent->aiOvfl[0]) ){
if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
apDiv[i] = pParent->apOvfl[0];
pgno = get4byte(apDiv[i]);
szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
+4 -1
View File
@@ -716,7 +716,10 @@ int sqlite3FindDbName(sqlite3 *db, const char *zName){
if( zName ){
Db *pDb;
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
if( 0==sqlite3StrICmp(pDb->zDbSName, zName) ) break;
if( 0==sqlite3_stricmp(pDb->zDbSName, zName) ) break;
/* "main" is always an acceptable alias for the primary database
** even if it has been renamed using SQLITE_DBCONFIG_MAINDBNAME. */
if( i==0 && 0==sqlite3_stricmp("main", zName) ) break;
}
}
return i;
+10 -1
View File
@@ -395,13 +395,22 @@ static int parseDateOrTime(
return 1;
}
/* The julian day number for 9999-12-31 23:59:59.999 is 5373484.4999999.
** Multiplying this by 86400000 gives 464269060799999 as the maximum value
** for DateTime.iJD.
**
** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with
** such a large integer literal, so we have to encode it.
*/
#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff)
/*
** Return TRUE if the given julian day number is within range.
**
** The input is the JulianDay times 86400000.
*/
static int validJulianDay(sqlite3_int64 iJD){
return iJD>=0 && iJD<=464269060799999;
return iJD>=0 && iJD<=INT_464269060799999;
}
/*
+94 -40
View File
@@ -414,9 +414,10 @@ Expr *sqlite3ExprForVectorField(
assert( pVector->flags & EP_xIsSelect );
/* The TK_SELECT_COLUMN Expr node:
**
** pLeft: pVector containing TK_SELECT
** pLeft: pVector containing TK_SELECT. Not deleted.
** pRight: not used. But recursively deleted.
** iColumn: Index of a column in pVector
** iTable: 0 or the number of columns on the LHS of an assignment
** pLeft->iTable: First in an array of register holding result, or 0
** if the result is not yet computed.
**
@@ -527,7 +528,10 @@ static void codeVectorCompare(
u8 opx = op;
int addrDone = sqlite3VdbeMakeLabel(v);
assert( nLeft==sqlite3ExprVectorSize(pRight) );
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused");
return;
}
assert( pExpr->op==TK_EQ || pExpr->op==TK_NE
|| pExpr->op==TK_IS || pExpr->op==TK_ISNOT
|| pExpr->op==TK_LT || pExpr->op==TK_GT
@@ -934,7 +938,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
** variable number.
**
** Wildcards of the form "?nnn" are assigned the number "nnn". We make
** sure "nnn" is not too be to avoid a denial of service attack when
** sure "nnn" is not too big to avoid a denial of service attack when
** the SQL statement comes from an external source.
**
** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
@@ -945,6 +949,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
sqlite3 *db = pParse->db;
const char *z;
ynVar x;
if( pExpr==0 ) return;
assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
@@ -955,9 +960,9 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
if( z[1]==0 ){
/* Wildcard of the form "?". Assign the next variable number */
assert( z[0]=='?' );
pExpr->iColumn = (ynVar)(++pParse->nVar);
x = (ynVar)(++pParse->nVar);
}else{
ynVar x;
int doAdd = 0;
if( z[0]=='?' ){
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
** use it as the variable number */
@@ -973,40 +978,29 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
return;
}
if( i>pParse->nVar ){
pParse->nVar = (int)i;
if( x>pParse->nVar ){
pParse->nVar = (int)x;
doAdd = 1;
}else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){
doAdd = 1;
}
}else{
/* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
** number as the prior appearance of the same name, or if the name
** has never appeared before, reuse the same variable number
*/
ynVar i;
for(i=x=0; i<pParse->nzVar; i++){
if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
x = (ynVar)i+1;
break;
}
x = (ynVar)sqlite3VListNameToNum(pParse->pVList, z, n);
if( x==0 ){
x = (ynVar)(++pParse->nVar);
doAdd = 1;
}
if( x==0 ) x = (ynVar)(++pParse->nVar);
}
pExpr->iColumn = x;
if( x>pParse->nzVar ){
char **a;
a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
if( a==0 ){
assert( db->mallocFailed ); /* Error reported through mallocFailed */
return;
}
pParse->azVar = a;
memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
pParse->nzVar = x;
if( doAdd ){
pParse->pVList = sqlite3VListAdd(db, pParse->pVList, z, n, x);
}
if( pParse->azVar[x-1]==0 ){
pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
}
}
if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
}
pExpr->iColumn = x;
if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "too many SQL variables");
}
}
@@ -1095,7 +1089,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
assert( EXPR_FULLSIZE<=0xfff );
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
if( 0==flags ){
if( 0==flags || p->op==TK_SELECT_COLUMN ){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
@@ -1238,6 +1232,8 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
assert( p->iColumn==0 || p->pRight==0 );
assert( p->pRight==0 || p->pRight==p->pLeft );
}else{
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
}
@@ -1300,6 +1296,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
ExprList *pNew;
struct ExprList_item *pItem, *pOldItem;
int i;
Expr *pPriorSelectCol = 0;
assert( db!=0 );
if( p==0 ) return 0;
pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
@@ -1314,7 +1311,24 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
Expr *pNewExpr;
pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
if( pOldExpr
&& pOldExpr->op==TK_SELECT_COLUMN
&& (pNewExpr = pItem->pExpr)!=0
){
assert( pNewExpr->iColumn==0 || i>0 );
if( pNewExpr->iColumn==0 ){
assert( pOldExpr->pLeft==pOldExpr->pRight );
pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
}else{
assert( i>0 );
assert( pItem[-1].pExpr!=0 );
assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
pNewExpr->pLeft = pPriorSelectCol;
}
}
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->sortOrder = pOldItem->sortOrder;
@@ -1489,7 +1503,7 @@ no_mem:
** Or: (a,b,c) = (SELECT x,y,z FROM ....)
**
** For each term of the vector assignment, append new entries to the
** expression list pList. In the case of a subquery on the LHS, append
** expression list pList. In the case of a subquery on the RHS, append
** TK_SELECT_COLUMN expressions.
*/
ExprList *sqlite3ExprListAppendVector(
@@ -1506,13 +1520,19 @@ ExprList *sqlite3ExprListAppendVector(
** exit prior to this routine being invoked */
if( NEVER(pColumns==0) ) goto vector_append_error;
if( pExpr==0 ) goto vector_append_error;
n = sqlite3ExprVectorSize(pExpr);
if( pColumns->nId!=n ){
/* If the RHS is a vector, then we can immediately check to see that
** the size of the RHS and LHS match. But if the RHS is a SELECT,
** wildcards ("*") in the result set of the SELECT must be expanded before
** we can do the size check, so defer the size check until code generation.
*/
if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pColumns->nId, n);
goto vector_append_error;
}
for(i=0; i<n; i++){
for(i=0; i<pColumns->nId; i++){
Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
if( pList ){
@@ -1521,11 +1541,20 @@ ExprList *sqlite3ExprListAppendVector(
pColumns->a[i].zName = 0;
}
}
if( pExpr->op==TK_SELECT ){
if( pList && pList->a[iFirst].pExpr ){
assert( pList->a[iFirst].pExpr->op==TK_SELECT_COLUMN );
pList->a[iFirst].pExpr->pRight = pExpr;
Expr *pFirst = pList->a[iFirst].pExpr;
assert( pFirst->op==TK_SELECT_COLUMN );
/* Store the SELECT statement in pRight so it will be deleted when
** sqlite3ExprListDelete() is called */
pFirst->pRight = pExpr;
pExpr = 0;
/* Remember the size of the LHS in iTable so that we can check that
** the RHS and LHS sizes match during code generation. */
pFirst->iTable = pColumns->nId;
}
}
@@ -3430,9 +3459,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
assert( pExpr->u.zToken[0]!=0 );
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
if( pExpr->u.zToken[1]!=0 ){
assert( pExpr->u.zToken[0]=='?'
|| strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
sqlite3VdbeAppendP4(v, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 );
pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
}
return target;
}
@@ -3630,6 +3660,22 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
}
#ifdef SQLITE_DEBUG
/* The AFFINITY() function evaluates to a string that describes
** the type affinity of the argument. This is used for testing of
** the SQLite type logic.
*/
if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
char aff;
assert( nFarg==1 );
aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
sqlite3VdbeLoadString(v, target,
aff ? azAff[aff-SQLITE_AFF_BLOB] : "none");
return target;
}
#endif
for(i=0; i<nFarg; i++){
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
testcase( i==31 );
@@ -3718,9 +3764,17 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
break;
}
case TK_SELECT_COLUMN: {
int n;
if( pExpr->pLeft->iTable==0 ){
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
}
assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
if( pExpr->iTable
&& pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pExpr->iTable, n);
}
return pExpr->pLeft->iTable + pExpr->iColumn;
}
case TK_IN: {
+25 -19
View File
@@ -200,25 +200,28 @@ static void instrFunc(
if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
nHaystack = sqlite3_value_bytes(argv[0]);
nNeedle = sqlite3_value_bytes(argv[1]);
if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
zHaystack = sqlite3_value_blob(argv[0]);
zNeedle = sqlite3_value_blob(argv[1]);
isText = 0;
}else{
zHaystack = sqlite3_value_text(argv[0]);
zNeedle = sqlite3_value_text(argv[1]);
isText = 1;
if( zNeedle==0 ) return;
assert( zHaystack );
if( nNeedle>0 ){
if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
zHaystack = sqlite3_value_blob(argv[0]);
zNeedle = sqlite3_value_blob(argv[1]);
assert( zNeedle!=0 );
assert( zHaystack!=0 || nHaystack==0 );
isText = 0;
}else{
zHaystack = sqlite3_value_text(argv[0]);
zNeedle = sqlite3_value_text(argv[1]);
isText = 1;
if( zHaystack==0 || zNeedle==0 ) return;
}
while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
N++;
do{
nHaystack--;
zHaystack++;
}while( isText && (zHaystack[0]&0xc0)==0x80 );
}
if( nNeedle>nHaystack ) N = 0;
}
while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
N++;
do{
nHaystack--;
zHaystack++;
}while( isText && (zHaystack[0]&0xc0)==0x80 );
}
if( nNeedle>nHaystack ) N = 0;
sqlite3_result_int(context, N);
}
@@ -1631,7 +1634,7 @@ static void groupConcatStep(
zSep = ",";
nSep = 1;
}
if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
}
zVal = (char*)sqlite3_value_text(argv[0]);
nVal = sqlite3_value_bytes(argv[0]);
@@ -1772,6 +1775,9 @@ void sqlite3RegisterBuiltinFunctions(void){
FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_DEBUG
FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
FUNCTION(rtrim, 1, 2, 0, trimFunc ),
+14 -2
View File
@@ -169,6 +169,19 @@ const unsigned char sqlite3CtypeMap[256] = {
# define SQLITE_STMTJRNL_SPILL (64*1024)
#endif
/*
** The default lookaside-configuration, the format "SZ,N". SZ is the
** number of bytes in each lookaside slot (should be a multiple of 8)
** and N is the number of slots. The lookaside-configuration can be
** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
** or at run-time for an individual database connection using
** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
*/
#ifndef SQLITE_DEFAULT_LOOKASIDE
# define SQLITE_DEFAULT_LOOKASIDE 1200,100
#endif
/*
** The following singleton contains the global configuration for
** the SQLite library.
@@ -181,8 +194,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
128, /* szLookaside */
500, /* nLookaside */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
SQLITE_STMTJRNL_SPILL, /* nStmtSpill */
{0,0,0,0,0,0,0,0}, /* m */
{0,0,0,0,0,0,0,0,0}, /* mutex */
+6 -11
View File
@@ -1568,7 +1568,7 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){
*/
void sqlite3_interrupt(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){
(void)SQLITE_MISUSE_BKPT;
return;
}
@@ -2739,7 +2739,9 @@ int sqlite3ParseUri(
}else{
zFile = sqlite3_malloc64(nUri+2);
if( !zFile ) return SQLITE_NOMEM_BKPT;
memcpy(zFile, zUri, nUri);
if( nUri ){
memcpy(zFile, zUri, nUri);
}
zFile[nUri] = '\0';
zFile[nUri+1] = '\0';
flags &= ~SQLITE_OPEN_URI;
@@ -3926,15 +3928,8 @@ sqlite3_int64 sqlite3_uri_int64(
** Return the Btree pointer identified by zDbName. Return NULL if not found.
*/
Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
int i;
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt
&& (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zDbSName)==0)
){
return db->aDb[i].pBt;
}
}
return 0;
int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0;
return iDb<0 ? 0 : db->aDb[iDb].pBt;
}
/*
+1 -1
View File
@@ -519,7 +519,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
}
+6 -4
View File
@@ -3964,6 +3964,7 @@ static int pagerSyncHotJournal(Pager *pPager){
return rc;
}
#if SQLITE_MAX_MMAP_SIZE>0
/*
** Obtain a reference to a memory mapped page object for page number pgno.
** The new object will use the pointer pData, obtained from xFetch().
@@ -4012,6 +4013,7 @@ static int pagerAcquireMapPage(
return SQLITE_OK;
}
#endif
/*
** Release a reference to page pPg. pPg must have been returned by an
@@ -5371,6 +5373,7 @@ static int getPageNormal(
assert( assert_pager_state(pPager) );
assert( pPager->hasHeldSharedLock==1 );
if( pgno==0 ) return SQLITE_CORRUPT_BKPT;
pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
if( pBase==0 ){
pPg = 0;
@@ -5398,11 +5401,10 @@ static int getPageNormal(
/* The pager cache has created a new page. Its content needs to
** be initialized. But first some error checks:
**
** (1) Minimum page number is 1
** (2) The maximum page number is 2^31
** (3) Never try to fetch the locking page
** (1) The maximum page number is 2^31
** (2) Never try to fetch the locking page
*/
if( pgno==0 || pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
rc = SQLITE_CORRUPT_BKPT;
goto pager_acquire_err;
}
+4
View File
@@ -1996,6 +1996,8 @@ static int pragmaVtabConnect(
StrAccum acc;
char zBuf[200];
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x");
for(i=0, j=pPragma->iPragCName; i<pPragma->nPragCName; i++, j++){
@@ -2152,6 +2154,8 @@ static int pragmaVtabFilter(
StrAccum acc;
char *zSql;
UNUSED_PARAMETER(idxNum);
UNUSED_PARAMETER(idxStr);
pragmaVtabCursorClear(pCsr);
j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1;
for(i=0; i<argc; i++, j++){
+1 -1
View File
@@ -841,7 +841,7 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
assert( p->accError==0 || p->nAlloc==0 );
if( p->nChar+N >= p->nAlloc ){
enlargeAndAppend(p,z,N);
}else{
}else if( N ){
assert( p->zText );
p->nChar += N;
memcpy(&p->zText[p->nChar-N], z, N);
+5 -2
View File
@@ -596,7 +596,7 @@ static void pushOntoSorter(
** register is initialized with value of LIMIT+OFFSET.) After the sorter
** fills up, delete the least entry in the sorter after each insert.
** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */
addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
if( pSort->bOrderedInnerLoop ){
r1 = ++pParse->nMem;
@@ -2037,6 +2037,7 @@ static void generateWithRecursiveQuery(
/* Process the LIMIT and OFFSET clauses, if they exist */
addrBreak = sqlite3VdbeMakeLabel(v);
p->nSelectRow = 320; /* 4 billion rows */
computeLimitRegisters(pParse, p, addrBreak);
pLimit = p->pLimit;
pOffset = p->pOffset;
@@ -5170,7 +5171,9 @@ int sqlite3Select(
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(v);
p->nSelectRow = 320; /* 4 billion rows */
if( (p->selFlags & SF_FixedLimit)==0 ){
p->nSelectRow = 320; /* 4 billion rows */
}
computeLimitRegisters(pParse, p, iEnd);
if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
+58 -79
View File
@@ -2280,14 +2280,22 @@ void session_help(ShellState *p){
/* Forward reference */
static int process_input(ShellState *p, FILE *in);
/*
** Read the content of a file into memory obtained from sqlite3_malloc64().
** The caller is responsible for freeing the memory.
** Read the content of file zName into memory obtained from sqlite3_malloc64()
** and return a pointer to the buffer. The caller is responsible for freeing
** the memory.
**
** NULL is returned if any error is encountered.
** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
** read.
**
** For convenience, a nul-terminator byte is always appended to the data read
** from the file before the buffer is returned. This byte is not included in
** the final value of (*pnByte), if applicable.
**
** NULL is returned if any error is encountered. The final value of *pnByte
** is undefined in this case.
*/
static char *readFile(const char *zName){
static char *readFile(const char *zName, int *pnByte){
FILE *in = fopen(zName, "rb");
long nIn;
size_t nRead;
@@ -2305,6 +2313,7 @@ static char *readFile(const char *zName){
return 0;
}
pBuf[nIn] = 0;
if( pnByte ) *pnByte = nIn;
return pBuf;
}
@@ -2320,12 +2329,13 @@ static void readfileFunc(
){
const char *zName;
void *pBuf;
int nBuf;
UNUSED_PARAMETER(argc);
zName = (const char*)sqlite3_value_text(argv[0]);
if( zName==0 ) return;
pBuf = readFile(zName);
if( pBuf ) sqlite3_result_blob(context, pBuf, -1, sqlite3_free);
pBuf = readFile(zName, &nBuf);
if( pBuf ) sqlite3_result_blob(context, pBuf, nBuf, sqlite3_free);
}
/*
@@ -3282,7 +3292,7 @@ static void shellFkeyCollateClause(
const char *zParentSeq;
const char *zChild;
const char *zChildCol;
const char *zChildSeq;
const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
int rc;
assert( nVal==4 );
@@ -3390,7 +3400,7 @@ static int lintFkeyIndexes(
;
for(i=2; i<nArg; i++){
int n = strlen(azArg[i]);
int n = (int)strlen(azArg[i]);
if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
bVerbose = 1;
}
@@ -3490,7 +3500,7 @@ static int lintDotCommand(
int nArg /* Number of entries in azArg[] */
){
int n;
n = (nArg>=2 ? strlen(azArg[1]) : 0);
n = (nArg>=2 ? (int)strlen(azArg[1]) : 0);
if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
return lintFkeyIndexes(pState, azArg, nArg);
@@ -3665,7 +3675,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( nArg!=2 ){
raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
rc = 2;
}else if( (zRes = readFile("testcase-out.txt"))==0 ){
}else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
rc = 2;
}else if( testcase_glob(azArg[1],zRes)==0 ){
@@ -3694,13 +3704,12 @@ static int do_meta_command(char *zLine, ShellState *p){
char *zErrMsg = 0;
open_db(p, 0);
memcpy(&data, p, sizeof(data));
data.showHeader = 1;
data.cMode = data.mode = MODE_Column;
data.colWidth[0] = 3;
data.colWidth[1] = 15;
data.colWidth[2] = 58;
data.showHeader = 0;
data.cMode = data.mode = MODE_List;
sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
data.cnt = 0;
sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
callback, &data, &zErrMsg);
if( zErrMsg ){
utf8_printf(stderr,"Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
@@ -4081,52 +4090,6 @@ static int do_meta_command(char *zLine, ShellState *p){
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
}else
if( c=='i' && (strncmp(azArg[0], "indices", n)==0
|| strncmp(azArg[0], "indexes", n)==0) ){
ShellState data;
char *zErrMsg = 0;
open_db(p, 0);
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
data.cMode = data.mode = MODE_List;
if( nArg==1 ){
rc = sqlite3_exec(p->db,
"SELECT name FROM sqlite_master "
"WHERE type='index' AND name NOT LIKE 'sqlite_%' "
"UNION ALL "
"SELECT name FROM sqlite_temp_master "
"WHERE type='index' "
"ORDER BY 1",
callback, &data, &zErrMsg
);
}else if( nArg==2 ){
zShellStatic = azArg[1];
rc = sqlite3_exec(p->db,
"SELECT name FROM sqlite_master "
"WHERE type='index' AND tbl_name LIKE shellstatic() "
"UNION ALL "
"SELECT name FROM sqlite_temp_master "
"WHERE type='index' AND tbl_name LIKE shellstatic() "
"ORDER BY 1",
callback, &data, &zErrMsg
);
zShellStatic = 0;
}else{
raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
rc = 1;
goto meta_command_exit;
}
if( zErrMsg ){
utf8_printf(stderr,"Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
rc = 1;
}else if( rc != SQLITE_OK ){
raw_printf(stderr,
"Error: querying sqlite_master and sqlite_temp_master\n");
rc = 1;
}
}else
#ifndef SQLITE_UNTESTABLE
if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
char *zSql;
@@ -4950,7 +4913,10 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
|| (c=='i' && (strncmp(azArg[0], "indices", n)==0
|| strncmp(azArg[0], "indexes", n)==0) )
){
sqlite3_stmt *pStmt;
char **azResult;
int nRow, nAlloc;
@@ -4963,28 +4929,41 @@ static int do_meta_command(char *zLine, ShellState *p){
/* Create an SQL statement to query for the list of tables in the
** main and all attached databases where the table name matches the
** LIKE pattern bound to variable "?1". */
zSql = sqlite3_mprintf(
"SELECT name FROM sqlite_master"
" WHERE type IN ('table','view')"
" AND name NOT LIKE 'sqlite_%%'"
" AND name LIKE ?1");
while( zSql && sqlite3_step(pStmt)==SQLITE_ROW ){
if( c=='t' ){
zSql = sqlite3_mprintf(
"SELECT name FROM sqlite_master"
" WHERE type IN ('table','view')"
" AND name NOT LIKE 'sqlite_%%'"
" AND name LIKE ?1");
}else if( nArg>2 ){
/* It is an historical accident that the .indexes command shows an error
** when called with the wrong number of arguments whereas the .tables
** command does not. */
raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
rc = 1;
goto meta_command_exit;
}else{
zSql = sqlite3_mprintf(
"SELECT name FROM sqlite_master"
" WHERE type='index'"
" AND tbl_name LIKE ?1");
}
for(ii=0; zSql && sqlite3_step(pStmt)==SQLITE_ROW; ii++){
const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue;
if( strcmp(zDbName,"temp")==0 ){
zSql = sqlite3_mprintf(
"%z UNION ALL "
"SELECT 'temp.' || name FROM sqlite_temp_master"
" WHERE type IN ('table','view')"
" AND name NOT LIKE 'sqlite_%%'"
" AND name LIKE ?1", zSql);
}else{
if( zDbName==0 || ii==0 ) continue;
if( c=='t' ){
zSql = sqlite3_mprintf(
"%z UNION ALL "
"SELECT '%q.' || name FROM \"%w\".sqlite_master"
" WHERE type IN ('table','view')"
" AND name NOT LIKE 'sqlite_%%'"
" AND name LIKE ?1", zSql, zDbName, zDbName);
}else{
zSql = sqlite3_mprintf(
"%z UNION ALL "
"SELECT '%q.' || name FROM \"%w\".sqlite_master"
" WHERE type='index'"
" AND tbl_name LIKE ?1", zSql, zDbName, zDbName);
}
}
rc = sqlite3_finalize(pStmt);
+18 -3
View File
@@ -587,9 +587,12 @@
** pagecaches for each database connection. A positive number is the
** number of pages. A negative number N translations means that a buffer
** of -1024*N bytes is allocated and used for as many pages as it will hold.
**
** The default value of "20" was choosen to minimize the run-time of the
** speedtest1 test program with options: --shrink-memory --reprepare
*/
#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
# define SQLITE_DEFAULT_PCACHE_INITSZ 100
# define SQLITE_DEFAULT_PCACHE_INITSZ 20
#endif
/*
@@ -1046,6 +1049,14 @@ typedef struct Walker Walker;
typedef struct WhereInfo WhereInfo;
typedef struct With With;
/* A VList object records a mapping between parameters/variables/wildcards
** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
** variable number associated with that parameter. See the format description
** on the sqlite3VListAdd() routine for more information. A VList is really
** just an array of integers.
*/
typedef int VList;
/*
** Defer sourcing vdbe.h and btree.h until after the "u8" and
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
@@ -1288,6 +1299,7 @@ struct sqlite3 {
u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
u8 mTrace; /* zero or more SQLITE_TRACE flags */
u8 skipBtreeMutex; /* True if no shared-cache backends */
int nextPagesize; /* Pagesize after VACUUM if >0 */
u32 magic; /* Magic number for detect library misuse */
int nChange; /* Value returned by sqlite3_changes() */
@@ -1553,6 +1565,7 @@ struct FuncDestructor {
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -2952,7 +2965,6 @@ struct Parse {
Token sLastToken; /* The last token parsed */
ynVar nVar; /* Number of '?' variables seen in the SQL so far */
int nzVar; /* Number of available slots in azVar[] */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 explain; /* True if the EXPLAIN flag is found on the query */
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -2964,7 +2976,7 @@ struct Parse {
int iSelectId; /* ID of current select for EXPLAIN output */
int iNextSelectId; /* Next available select ID for EXPLAIN output */
#endif
char **azVar; /* Pointers to names of parameters */
VList *pVList; /* Mapping between variable names and numbers */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
@@ -3864,6 +3876,9 @@ LogEst sqlite3LogEstFromDouble(double);
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
u64 sqlite3LogEstToInt(LogEst);
#endif
VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
const char *sqlite3VListNumToName(VList*,int);
int sqlite3VListNameToNum(VList*,const char*,int);
/*
** Routines to read and write variable-length integers. These used to
+2 -4
View File
@@ -500,8 +500,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
assert( pParse->pNewTable==0 );
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
assert( pParse->nzVar==0 );
assert( pParse->azVar==0 );
assert( pParse->pVList==0 );
while( 1 ){
assert( i>=0 );
if( zSql[i]!=0 ){
@@ -588,8 +587,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
sqlite3DbFree(db, pParse->azVar);
sqlite3DbFree(db, pParse->pVList);
while( pParse->pAinc ){
AutoincInfo *p = pParse->pAinc;
pParse->pAinc = p->pNext;
+103
View File
@@ -1453,3 +1453,106 @@ u64 sqlite3LogEstToInt(LogEst x){
return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
}
#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */
/*
** Add a new name/number pair to a VList. This might require that the
** VList object be reallocated, so return the new VList. If an OOM
** error occurs, the original VList returned and the
** db->mallocFailed flag is set.
**
** A VList is really just an array of integers. To destroy a VList,
** simply pass it to sqlite3DbFree().
**
** The first integer is the number of integers allocated for the whole
** VList. The second integer is the number of integers actually used.
** Each name/number pair is encoded by subsequent groups of 3 or more
** integers.
**
** Each name/number pair starts with two integers which are the numeric
** value for the pair and the size of the name/number pair, respectively.
** The text name overlays one or more following integers. The text name
** is always zero-terminated.
**
** Conceptually:
**
** struct VList {
** int nAlloc; // Number of allocated slots
** int nUsed; // Number of used slots
** struct VListEntry {
** int iValue; // Value for this entry
** int nSlot; // Slots used by this entry
** // ... variable name goes here
** } a[0];
** }
**
** During code generation, pointers to the variable names within the
** VList are taken. When that happens, nAlloc is set to zero as an
** indication that the VList may never again be enlarged, since the
** accompanying realloc() would invalidate the pointers.
*/
VList *sqlite3VListAdd(
sqlite3 *db, /* The database connection used for malloc() */
VList *pIn, /* The input VList. Might be NULL */
const char *zName, /* Name of symbol to add */
int nName, /* Bytes of text in zName */
int iVal /* Value to associate with zName */
){
int nInt; /* number of sizeof(int) objects needed for zName */
char *z; /* Pointer to where zName will be stored */
int i; /* Index in pIn[] where zName is stored */
nInt = nName/4 + 3;
assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */
if( pIn==0 || pIn[1]+nInt > pIn[0] ){
/* Enlarge the allocation */
int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt;
VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int));
if( pOut==0 ) return pIn;
if( pIn==0 ) pOut[1] = 2;
pIn = pOut;
pIn[0] = nAlloc;
}
i = pIn[1];
pIn[i] = iVal;
pIn[i+1] = nInt;
z = (char*)&pIn[i+2];
pIn[1] = i+nInt;
assert( pIn[1]<=pIn[0] );
memcpy(z, zName, nName);
z[nName] = 0;
return pIn;
}
/*
** Return a pointer to the name of a variable in the given VList that
** has the value iVal. Or return a NULL if there is no such variable in
** the list
*/
const char *sqlite3VListNumToName(VList *pIn, int iVal){
int i, mx;
if( pIn==0 ) return 0;
mx = pIn[1];
i = 2;
do{
if( pIn[i]==iVal ) return (char*)&pIn[i+2];
i += pIn[i+1];
}while( i<mx );
return 0;
}
/*
** Return the number of the variable named zName, if it is in VList.
** or return 0 if there is no such variable.
*/
int sqlite3VListNameToNum(VList *pIn, const char *zName, int nName){
int i, mx;
if( pIn==0 ) return 0;
mx = pIn[1];
i = 2;
do{
const char *z = (const char*)&pIn[i+2];
if( strncmp(z,zName,nName)==0 && z[nName]==0 ) return pIn[i];
i += pIn[i+1];
}while( i<mx );
return 0;
}
+30 -16
View File
@@ -977,7 +977,7 @@ case OP_Halt: {
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
p->pc = pcx;
assert( pOp->p5>=0 && pOp->p5<=4 );
assert( pOp->p5<=4 );
if( p->rc ){
if( pOp->p5 ){
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
@@ -1190,7 +1190,7 @@ case OP_Variable: { /* out2 */
Mem *pVar; /* Value being transferred */
assert( pOp->p1>0 && pOp->p1<=p->nVar );
assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) );
pVar = &p->aVar[pOp->p1 - 1];
if( sqlite3VdbeMemTooBig(pVar) ){
goto too_big;
@@ -3783,7 +3783,8 @@ case OP_SeekGT: { /* jump, in3 */
if( pC->isTable ){
/* The BTREE_SEEK_EQ flag is only set on index cursors */
assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 );
assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0
|| CORRUPT_DB );
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
@@ -3985,10 +3986,9 @@ case OP_Found: { /* jump, in3 */
int ii;
VdbeCursor *pC;
int res;
char *pFree;
UnpackedRecord *pFree;
UnpackedRecord *pIdxKey;
UnpackedRecord r;
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7];
#ifdef SQLITE_TEST
if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
@@ -4005,7 +4005,6 @@ case OP_Found: { /* jump, in3 */
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
assert( pC->isTable==0 );
pFree = 0;
if( pOp->p4.i>0 ){
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
@@ -4018,10 +4017,9 @@ case OP_Found: { /* jump, in3 */
}
#endif
pIdxKey = &r;
pFree = 0;
}else{
pIdxKey = sqlite3VdbeAllocUnpackedRecord(
pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
);
pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
if( pIdxKey==0 ) goto no_mem;
assert( pIn3->flags & MEM_Blob );
(void)ExpandBlob(pIn3);
@@ -4041,7 +4039,7 @@ case OP_Found: { /* jump, in3 */
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
sqlite3DbFree(db, pFree);
if( pFree ) sqlite3DbFree(db, pFree);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@@ -4823,6 +4821,15 @@ case OP_Last: { /* jump */
}
/* Opcode: SorterSort P1 P2 * * *
**
** After all records have been inserted into the Sorter object
** identified by P1, invoke this opcode to actually do the sorting.
** Jump to P2 if there are no records to be sorted.
**
** This opcode is an alias for OP_Sort and OP_Rewind that is used
** for Sorter objects.
*/
/* Opcode: Sort P1 P2 * * *
**
** This opcode does exactly the same thing as OP_Rewind except that
@@ -4950,6 +4957,13 @@ case OP_Rewind: { /* jump */
** This opcode works just like Prev except that if cursor P1 is not
** open it behaves a no-op.
*/
/* Opcode: SorterNext P1 P2 * * P5
**
** This opcode works just like OP_Next except that P1 must be a
** sorter object for which the OP_SorterSort opcode has been
** invoked. This opcode advances the cursor to the next sorted
** record, or jumps to P2 if there are no more sorted records.
*/
case OP_SorterNext: { /* jump */
VdbeCursor *pC;
int res;
@@ -6012,20 +6026,20 @@ case OP_OffsetLimit: { /* in1, out2, in3 */
break;
}
/* Opcode: IfNotZero P1 P2 P3 * *
** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2
/* Opcode: IfNotZero P1 P2 * * *
** Synopsis: if r[P1]!=0 then r[P1]--, goto P2
**
** Register P1 must contain an integer. If the content of register P1 is
** initially nonzero, then subtract P3 from the value in register P1 and
** jump to P2. If register P1 is initially zero, leave it unchanged
** and fall through.
** initially greater than zero, then decrement the value in register P1.
** If it is non-zero (negative or positive) and then also jump to P2.
** If register P1 is initially zero, leave it unchanged and fall through.
*/
case OP_IfNotZero: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
VdbeBranchTaken(pIn1->u.i<0, 2);
if( pIn1->u.i ){
pIn1->u.i -= pOp->p3;
if( pIn1->u.i>0 ) pIn1->u.i--;
goto jump_to_p2;
}
break;
+1 -1
View File
@@ -233,7 +233,7 @@ int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
+1 -2
View File
@@ -346,7 +346,6 @@ struct Vdbe {
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
ynVar nzVar; /* Number of entries in azVar[] */
u32 magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
int nCursor; /* Number of slots in apCsr[] */
@@ -371,7 +370,7 @@ struct Vdbe {
char *zErrMsg; /* Error message written here */
VdbeCursor **apCsr; /* One element of this array for each open cursor */
Mem *aVar; /* Values for the OP_Variable opcode. */
char **azVar; /* Name of variables */
VList *pVList; /* Name of variables */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
+5 -19
View File
@@ -1470,10 +1470,8 @@ int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
*/
const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
Vdbe *p = (Vdbe*)pStmt;
if( p==0 || i<1 || i>p->nzVar ){
return 0;
}
return p->azVar[i-1];
if( p==0 ) return 0;
return sqlite3VListNumToName(p->pVList, i);
}
/*
@@ -1482,19 +1480,8 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
** return 0.
*/
int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
int i;
if( p==0 ){
return 0;
}
if( zName ){
for(i=0; i<p->nzVar; i++){
const char *z = p->azVar[i];
if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
return i+1;
}
}
}
return 0;
if( p==0 || zName==0 ) return 0;
return sqlite3VListNameToNum(p->pVList, zName, nName);
}
int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
@@ -1657,10 +1644,9 @@ static UnpackedRecord *vdbeUnpackRecord(
int nKey,
const void *pKey
){
char *dummy; /* Dummy argument for AllocUnpackedRecord() */
UnpackedRecord *pRet; /* Return value */
pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &dummy);
pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pRet ){
memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1));
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
+12 -30
View File
@@ -1975,10 +1975,8 @@ void sqlite3VdbeMakeReady(
x.nFree = x.nNeeded;
}while( !db->mallocFailed );
p->nzVar = pParse->nzVar;
p->azVar = pParse->azVar;
pParse->nzVar = 0;
pParse->azVar = 0;
p->pVList = pParse->pVList;
pParse->pVList = 0;
p->explain = pParse->explain;
if( db->mallocFailed ){
p->nVar = 0;
@@ -2972,7 +2970,6 @@ void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp, int mask){
*/
void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
SubProgram *pSub, *pNext;
int i;
assert( p->db==0 || p->db==db );
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
for(pSub=p->pProgram; pSub; pSub=pNext){
@@ -2982,18 +2979,20 @@ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
}
if( p->magic!=VDBE_MAGIC_INIT ){
releaseMemArray(p->aVar, p->nVar);
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
sqlite3DbFree(db, p->azVar);
sqlite3DbFree(db, p->pVList);
sqlite3DbFree(db, p->pFree);
}
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
for(i=0; i<p->nScan; i++){
sqlite3DbFree(db, p->aScan[i].zName);
{
int i;
for(i=0; i<p->nScan; i++){
sqlite3DbFree(db, p->aScan[i].zName);
}
sqlite3DbFree(db, p->aScan);
}
sqlite3DbFree(db, p->aScan);
#endif
}
@@ -3494,30 +3493,13 @@ u32 sqlite3VdbeSerialGet(
** If an OOM error occurs, NULL is returned.
*/
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
KeyInfo *pKeyInfo, /* Description of the record */
char *pSpace, /* Unaligned space available */
int szSpace, /* Size of pSpace[] in bytes */
char **ppFree /* OUT: Caller should free this pointer */
KeyInfo *pKeyInfo /* Description of the record */
){
UnpackedRecord *p; /* Unpacked record to return */
int nOff; /* Increment pSpace by nOff to align it */
int nByte; /* Number of bytes required for *p */
/* We want to shift the pointer pSpace up such that it is 8-byte aligned.
** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
** it by. If pSpace is already 8-byte aligned, nOff should be zero.
*/
nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
if( nByte>szSpace+nOff ){
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
*ppFree = (char *)p;
if( !p ) return 0;
}else{
p = (UnpackedRecord*)&pSpace[nOff];
*ppFree = 0;
}
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
assert( pKeyInfo->aSortOrder!=0 );
p->pKeyInfo = pKeyInfo;
+3 -9
View File
@@ -1327,12 +1327,8 @@ static int vdbeSorterOpenTempFile(
*/
static int vdbeSortAllocUnpacked(SortSubtask *pTask){
if( pTask->pUnpacked==0 ){
char *pFree;
pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(
pTask->pSorter->pKeyInfo, 0, 0, &pFree
);
assert( pTask->pUnpacked==(UnpackedRecord*)pFree );
if( pFree==0 ) return SQLITE_NOMEM_BKPT;
pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo);
if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT;
pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField;
pTask->pUnpacked->errCode = 0;
}
@@ -2733,9 +2729,7 @@ int sqlite3VdbeSorterCompare(
r2 = pSorter->pUnpacked;
pKeyInfo = pCsr->pKeyInfo;
if( r2==0 ){
char *p;
r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo,0,0,&p);
assert( pSorter->pUnpacked==(UnpackedRecord*)p );
r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( r2==0 ) return SQLITE_NOMEM_BKPT;
r2->nField = nKeyCol;
}
+9 -2
View File
@@ -100,6 +100,12 @@ do_test corruptC-2.1 {
} {1 {database disk image is malformed}}
# test that a corrupt content offset size is handled (seed 5649)
#
# Update 2016-12-27: As of check-in [0b86fbca66] "In sqlite3BtreeInsert() when
# replacing a re-existing row, try to overwrite the cell directly rather than
# deallocate and reallocate the cell" on 2016-12-09, this test case no longer
# detects the offset size problem during the UPDATE. We have to run a subsequent
# integrity_check to see it.
do_test corruptC-2.2 {
db close
forcecopy test.bu test.db
@@ -117,8 +123,9 @@ do_test corruptC-2.2 {
hexio_write test.db 3746 [format %02x 0x9a]
sqlite3 db test.db
catchsql {UPDATE t1 SET y=1}
} {1 {database disk image is malformed}}
db eval {UPDATE t1 SET y=1}
db eval {PRAGMA integrity_check}
} {/Offset .* out of range/}
# test that a corrupt free cell size is handled (seed 13329)
do_test corruptC-2.3 {
+754
View File
@@ -0,0 +1,754 @@
/*
** 2016-12-17
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This program is designed for fuzz-testing SQLite database files.
**
** This program reads fuzzed database files from the disk files named
** on the command-line. Each database is loaded into an in-memory
** filesystem so that the original database file is unmolested.
**
** The fuzzed database is then opened, and series of SQL statements
** are run against the database to ensure that SQLite can safely handle
** the fuzzed database.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
#include "sqlite3.h"
#ifdef __unix__
# include <signal.h>
# include <unistd.h>
#endif
/*
** Print sketchy documentation for this utility program
*/
static void showHelp(const char *zArgv0){
printf("Usage: %s [options] DATABASE ...\n", zArgv0);
printf(
"Read databases into an in-memory filesystem. Run test SQL as specified\n"
"by command-line arguments or from\n"
"\n"
" SELECT group_concat(sql) FROM autoexec;\n"
"\n"
"Options:\n"
" --help Show this help text\n"
" -q|--quiet Reduced output\n"
" --limit-mem N Limit memory used by test SQLite instances to N bytes\n"
" --limit-vdbe Panic if any test runs for more than 100,000 cycles\n"
" --no-lookaside Disable the lookaside memory allocator\n"
" --timeout N Timeout after N seconds.\n"
" --trace Show the results of each SQL command\n"
" -v|--verbose Increased output. Repeat for more output.\n"
);
exit(0);
}
/*
** Print an error message and quit.
*/
static void fatalError(const char *zFormat, ...){
va_list ap;
va_start(ap, zFormat);
vfprintf(stderr, zFormat, ap);
va_end(ap);
fprintf(stderr, "\n");
exit(1);
}
/*
** Files in the virtual file system.
*/
typedef struct VFile VFile;
typedef struct VHandle VHandle;
struct VFile {
char *zFilename; /* Filename. NULL for delete-on-close. From malloc() */
int sz; /* Size of the file in bytes */
int nRef; /* Number of references to this file */
unsigned char *a; /* Content of the file. From malloc() */
};
struct VHandle {
sqlite3_file base; /* Base class. Must be first */
VFile *pVFile; /* The underlying file */
};
/*
** Maximum number of files in the in-memory virtual filesystem.
*/
#define MX_FILE 10
/*
** Maximum allowed file size
*/
#define MX_FILE_SZ 1000000
/*
** All global variables are gathered into the "g" singleton.
*/
static struct GlobalVars {
VFile aFile[MX_FILE]; /* The virtual filesystem */
} g;
/*
** Initialize the virtual file system.
*/
static void formatVfs(void){
int i;
for(i=0; i<MX_FILE; i++){
g.aFile[i].sz = -1;
g.aFile[i].zFilename = 0;
g.aFile[i].a = 0;
g.aFile[i].nRef = 0;
}
}
/*
** Erase all information in the virtual file system.
*/
static void reformatVfs(void){
int i;
for(i=0; i<MX_FILE; i++){
if( g.aFile[i].sz<0 ) continue;
if( g.aFile[i].zFilename ){
free(g.aFile[i].zFilename);
g.aFile[i].zFilename = 0;
}
if( g.aFile[i].nRef>0 ){
fatalError("file %d still open. nRef=%d", i, g.aFile[i].nRef);
}
g.aFile[i].sz = -1;
free(g.aFile[i].a);
g.aFile[i].a = 0;
g.aFile[i].nRef = 0;
}
}
/*
** Find a VFile by name
*/
static VFile *findVFile(const char *zName){
int i;
if( zName==0 ) return 0;
for(i=0; i<MX_FILE; i++){
if( g.aFile[i].zFilename==0 ) continue;
if( strcmp(g.aFile[i].zFilename, zName)==0 ) return &g.aFile[i];
}
return 0;
}
/*
** Find a VFile called zName. Initialize it to the content of
** disk file zDiskFile.
**
** Return NULL if the filesystem is full.
*/
static VFile *createVFile(const char *zName, const char *zDiskFile){
VFile *pNew = findVFile(zName);
int i;
FILE *in = 0;
long sz = 0;
if( pNew ) return pNew;
for(i=0; i<MX_FILE && g.aFile[i].sz>=0; i++){}
if( i>=MX_FILE ) return 0;
if( zDiskFile ){
in = fopen(zDiskFile, "rb");
if( in==0 ) fatalError("no such file: \"%s\"", zDiskFile);
fseek(in, 0, SEEK_END);
sz = ftell(in);
rewind(in);
}
pNew = &g.aFile[i];
if( zName ){
int nName = (int)strlen(zName)+1;
pNew->zFilename = malloc(nName);
if( pNew->zFilename==0 ){
if( in ) fclose(in);
return 0;
}
memcpy(pNew->zFilename, zName, nName);
}else{
pNew->zFilename = 0;
}
pNew->nRef = 0;
pNew->sz = sz;
pNew->a = malloc(sz);
if( sz>0 ){
if( pNew->a==0 || fread(pNew->a, sz, 1, in)<1 ){
free(pNew->zFilename);
free(pNew->a);
pNew->a = 0;
pNew->zFilename = 0;
pNew->sz = -1;
pNew = 0;
}
}
if( in ) fclose(in);
return pNew;
}
/* Methods for the VHandle object
*/
static int inmemClose(sqlite3_file *pFile){
VHandle *p = (VHandle*)pFile;
VFile *pVFile = p->pVFile;
pVFile->nRef--;
if( pVFile->nRef==0 && pVFile->zFilename==0 ){
pVFile->sz = -1;
free(pVFile->a);
pVFile->a = 0;
}
return SQLITE_OK;
}
static int inmemRead(
sqlite3_file *pFile, /* Read from this open file */
void *pData, /* Store content in this buffer */
int iAmt, /* Bytes of content */
sqlite3_int64 iOfst /* Start reading here */
){
VHandle *pHandle = (VHandle*)pFile;
VFile *pVFile = pHandle->pVFile;
if( iOfst<0 || iOfst>=pVFile->sz ){
memset(pData, 0, iAmt);
return SQLITE_IOERR_SHORT_READ;
}
if( iOfst+iAmt>pVFile->sz ){
memset(pData, 0, iAmt);
iAmt = (int)(pVFile->sz - iOfst);
memcpy(pData, pVFile->a, iAmt);
return SQLITE_IOERR_SHORT_READ;
}
memcpy(pData, pVFile->a + iOfst, iAmt);
return SQLITE_OK;
}
static int inmemWrite(
sqlite3_file *pFile, /* Write to this file */
const void *pData, /* Content to write */
int iAmt, /* bytes to write */
sqlite3_int64 iOfst /* Start writing here */
){
VHandle *pHandle = (VHandle*)pFile;
VFile *pVFile = pHandle->pVFile;
if( iOfst+iAmt > pVFile->sz ){
unsigned char *aNew;
if( iOfst+iAmt >= MX_FILE_SZ ){
return SQLITE_FULL;
}
aNew = realloc(pVFile->a, (int)(iOfst+iAmt));
if( aNew==0 ){
return SQLITE_FULL;
}
pVFile->a = aNew;
if( iOfst > pVFile->sz ){
memset(pVFile->a + pVFile->sz, 0, (int)(iOfst - pVFile->sz));
}
pVFile->sz = (int)(iOfst + iAmt);
}
memcpy(pVFile->a + iOfst, pData, iAmt);
return SQLITE_OK;
}
static int inmemTruncate(sqlite3_file *pFile, sqlite3_int64 iSize){
VHandle *pHandle = (VHandle*)pFile;
VFile *pVFile = pHandle->pVFile;
if( pVFile->sz>iSize && iSize>=0 ) pVFile->sz = (int)iSize;
return SQLITE_OK;
}
static int inmemSync(sqlite3_file *pFile, int flags){
return SQLITE_OK;
}
static int inmemFileSize(sqlite3_file *pFile, sqlite3_int64 *pSize){
*pSize = ((VHandle*)pFile)->pVFile->sz;
return SQLITE_OK;
}
static int inmemLock(sqlite3_file *pFile, int type){
return SQLITE_OK;
}
static int inmemUnlock(sqlite3_file *pFile, int type){
return SQLITE_OK;
}
static int inmemCheckReservedLock(sqlite3_file *pFile, int *pOut){
*pOut = 0;
return SQLITE_OK;
}
static int inmemFileControl(sqlite3_file *pFile, int op, void *pArg){
return SQLITE_NOTFOUND;
}
static int inmemSectorSize(sqlite3_file *pFile){
return 512;
}
static int inmemDeviceCharacteristics(sqlite3_file *pFile){
return
SQLITE_IOCAP_SAFE_APPEND |
SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
/* Method table for VHandle
*/
static sqlite3_io_methods VHandleMethods = {
/* iVersion */ 1,
/* xClose */ inmemClose,
/* xRead */ inmemRead,
/* xWrite */ inmemWrite,
/* xTruncate */ inmemTruncate,
/* xSync */ inmemSync,
/* xFileSize */ inmemFileSize,
/* xLock */ inmemLock,
/* xUnlock */ inmemUnlock,
/* xCheck... */ inmemCheckReservedLock,
/* xFileCtrl */ inmemFileControl,
/* xSectorSz */ inmemSectorSize,
/* xDevchar */ inmemDeviceCharacteristics,
/* xShmMap */ 0,
/* xShmLock */ 0,
/* xShmBarrier */ 0,
/* xShmUnmap */ 0,
/* xFetch */ 0,
/* xUnfetch */ 0
};
/*
** Open a new file in the inmem VFS. All files are anonymous and are
** delete-on-close.
*/
static int inmemOpen(
sqlite3_vfs *pVfs,
const char *zFilename,
sqlite3_file *pFile,
int openFlags,
int *pOutFlags
){
VFile *pVFile = createVFile(zFilename, 0);
VHandle *pHandle = (VHandle*)pFile;
if( pVFile==0 ){
return SQLITE_FULL;
}
pHandle->pVFile = pVFile;
pVFile->nRef++;
pFile->pMethods = &VHandleMethods;
if( pOutFlags ) *pOutFlags = openFlags;
return SQLITE_OK;
}
/*
** Delete a file by name
*/
static int inmemDelete(
sqlite3_vfs *pVfs,
const char *zFilename,
int syncdir
){
VFile *pVFile = findVFile(zFilename);
if( pVFile==0 ) return SQLITE_OK;
if( pVFile->nRef==0 ){
free(pVFile->zFilename);
pVFile->zFilename = 0;
pVFile->sz = -1;
free(pVFile->a);
pVFile->a = 0;
return SQLITE_OK;
}
return SQLITE_IOERR_DELETE;
}
/* Check for the existance of a file
*/
static int inmemAccess(
sqlite3_vfs *pVfs,
const char *zFilename,
int flags,
int *pResOut
){
VFile *pVFile = findVFile(zFilename);
*pResOut = pVFile!=0;
return SQLITE_OK;
}
/* Get the canonical pathname for a file
*/
static int inmemFullPathname(
sqlite3_vfs *pVfs,
const char *zFilename,
int nOut,
char *zOut
){
sqlite3_snprintf(nOut, zOut, "%s", zFilename);
return SQLITE_OK;
}
/*
** Register the VFS that reads from the g.aFile[] set of files.
*/
static void inmemVfsRegister(void){
static sqlite3_vfs inmemVfs;
sqlite3_vfs *pDefault = sqlite3_vfs_find(0);
inmemVfs.iVersion = 3;
inmemVfs.szOsFile = sizeof(VHandle);
inmemVfs.mxPathname = 200;
inmemVfs.zName = "inmem";
inmemVfs.xOpen = inmemOpen;
inmemVfs.xDelete = inmemDelete;
inmemVfs.xAccess = inmemAccess;
inmemVfs.xFullPathname = inmemFullPathname;
inmemVfs.xRandomness = pDefault->xRandomness;
inmemVfs.xSleep = pDefault->xSleep;
inmemVfs.xCurrentTimeInt64 = pDefault->xCurrentTimeInt64;
sqlite3_vfs_register(&inmemVfs, 0);
};
/*
** Timeout handler
*/
#ifdef __unix__
static void timeoutHandler(int NotUsed){
(void)NotUsed;
fatalError("timeout\n");
}
#endif
/*
** Set the an alarm to go off after N seconds. Disable the alarm
** if N==0
*/
static void setAlarm(int N){
#ifdef __unix__
alarm(N);
#else
(void)N;
#endif
}
/***************************************************************************
** String accumulator object
*/
typedef struct Str Str;
struct Str {
char *z; /* The string. Memory from malloc() */
sqlite3_uint64 n; /* Bytes of input used */
sqlite3_uint64 nAlloc; /* Bytes allocated to z[] */
int oomErr; /* OOM error has been seen */
};
/* Initialize a Str object */
static void StrInit(Str *p){
memset(p, 0, sizeof(*p));
}
/* Append text to the end of a Str object */
static void StrAppend(Str *p, const char *z){
sqlite3_uint64 n = strlen(z);
if( p->n + n >= p->nAlloc ){
char *zNew;
sqlite3_uint64 nNew;
if( p->oomErr ) return;
nNew = p->nAlloc*2 + 100 + n;
zNew = sqlite3_realloc(p->z, nNew);
if( zNew==0 ){
sqlite3_free(p->z);
memset(p, 0, sizeof(*p));
p->oomErr = 1;
return;
}
p->z = zNew;
p->nAlloc = nNew;
}
memcpy(p->z + p->n, z, n);
p->n += n;
p->z[p->n] = 0;
}
/* Return the current string content */
static char *StrStr(Str *p){
return p->z;
}
/* Free the string */
static void StrFree(Str *p){
sqlite3_free(p->z);
StrInit(p);
}
/*
** Return the value of a hexadecimal digit. Return -1 if the input
** is not a hex digit.
*/
static int hexDigitValue(char c){
if( c>='0' && c<='9' ) return c - '0';
if( c>='a' && c<='f' ) return c - 'a' + 10;
if( c>='A' && c<='F' ) return c - 'A' + 10;
return -1;
}
/*
** Interpret zArg as an integer value, possibly with suffixes.
*/
static int integerValue(const char *zArg){
sqlite3_int64 v = 0;
static const struct { char *zSuffix; int iMult; } aMult[] = {
{ "KiB", 1024 },
{ "MiB", 1024*1024 },
{ "GiB", 1024*1024*1024 },
{ "KB", 1000 },
{ "MB", 1000000 },
{ "GB", 1000000000 },
{ "K", 1000 },
{ "M", 1000000 },
{ "G", 1000000000 },
};
int i;
int isNeg = 0;
if( zArg[0]=='-' ){
isNeg = 1;
zArg++;
}else if( zArg[0]=='+' ){
zArg++;
}
if( zArg[0]=='0' && zArg[1]=='x' ){
int x;
zArg += 2;
while( (x = hexDigitValue(zArg[0]))>=0 ){
v = (v<<4) + x;
zArg++;
}
}else{
while( ISDIGIT(zArg[0]) ){
v = v*10 + zArg[0] - '0';
zArg++;
}
}
for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
v *= aMult[i].iMult;
break;
}
}
if( v>0x7fffffff ) fatalError("parameter too large - max 2147483648");
return (int)(isNeg? -v : v);
}
/*
** This callback is invoked by sqlite3_log().
*/
static void sqlLog(void *pNotUsed, int iErrCode, const char *zMsg){
printf("LOG: (%d) %s\n", iErrCode, zMsg);
fflush(stdout);
}
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
** This an SQL progress handler. After an SQL statement has run for
** many steps, we want to interrupt it. This guards against infinite
** loops from recursive common table expressions.
**
** *pVdbeLimitFlag is true if the --limit-vdbe command-line option is used.
** In that case, hitting the progress handler is a fatal error.
*/
static int progressHandler(void *pVdbeLimitFlag){
if( *(int*)pVdbeLimitFlag ) fatalError("too many VDBE cycles");
return 1;
}
#endif
/*
** Allowed values for the runFlags parameter to runSql()
*/
#define SQL_TRACE 0x0001 /* Print each SQL statement as it is prepared */
#define SQL_OUTPUT 0x0002 /* Show the SQL output */
/*
** Run multiple commands of SQL. Similar to sqlite3_exec(), but does not
** stop if an error is encountered.
*/
static void runSql(sqlite3 *db, const char *zSql, unsigned runFlags){
const char *zMore;
const char *zEnd = &zSql[strlen(zSql)];
sqlite3_stmt *pStmt;
while( zSql && zSql[0] ){
zMore = 0;
pStmt = 0;
sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore);
assert( zMore<=zEnd );
if( zMore==zSql ) break;
if( runFlags & SQL_TRACE ){
const char *z = zSql;
int n;
while( z<zMore && ISSPACE(z[0]) ) z++;
n = (int)(zMore - z);
while( n>0 && ISSPACE(z[n-1]) ) n--;
if( n==0 ) break;
if( pStmt==0 ){
printf("TRACE: %.*s (error: %s)\n", n, z, sqlite3_errmsg(db));
}else{
printf("TRACE: %.*s\n", n, z);
}
}
zSql = zMore;
if( pStmt ){
if( (runFlags & SQL_OUTPUT)==0 ){
while( SQLITE_ROW==sqlite3_step(pStmt) ){}
}else{
int nCol = -1;
int nRow;
for(nRow=0; SQLITE_ROW==sqlite3_step(pStmt); nRow++){
int i;
if( nCol<0 ){
nCol = sqlite3_column_count(pStmt);
}
for(i=0; i<nCol; i++){
int eType = sqlite3_column_type(pStmt,i);
printf("ROW[%d].%s = ", nRow, sqlite3_column_name(pStmt,i));
switch( eType ){
case SQLITE_NULL: {
printf("NULL\n");
break;
}
case SQLITE_INTEGER: {
printf("INT %s\n", sqlite3_column_text(pStmt,i));
break;
}
case SQLITE_FLOAT: {
printf("FLOAT %s\n", sqlite3_column_text(pStmt,i));
break;
}
case SQLITE_TEXT: {
printf("TEXT [%s]\n", sqlite3_column_text(pStmt,i));
break;
}
case SQLITE_BLOB: {
printf("BLOB (%d bytes)\n", sqlite3_column_bytes(pStmt,i));
break;
}
}
}
}
}
sqlite3_finalize(pStmt);
}
}
}
int main(int argc, char **argv){
int i; /* Loop counter */
int nDb = 0; /* Number of databases to fuzz */
const char **azDb = 0; /* Names of the databases (limit: 20) */
int verboseFlag = 0; /* True for extra output */
int noLookaside = 0; /* Disable lookaside if true */
int vdbeLimitFlag = 0; /* Stop after 100,000 VDBE ops */
int nHeap = 0; /* True for fixed heap size */
int iTimeout = 0; /* Timeout delay in seconds */
int rc; /* Result code from SQLite3 API calls */
sqlite3 *db; /* The database connection */
sqlite3_stmt *pStmt; /* A single SQL statement */
Str sql; /* SQL to run */
unsigned runFlags = 0; /* Flags passed to runSql */
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]!='-' ){
azDb = realloc(azDb, sizeof(azDb[0])*(nDb+1));
if( azDb==0 ) fatalError("out of memory");
azDb[nDb++] = z;
continue;
}
z++;
if( z[0]=='-' ) z++;
if( strcmp(z, "help")==0 ){
showHelp(argv[0]);
}else if( strcmp(z, "limit-mem")==0 ){
if( i==argc-1 ) fatalError("missing argument to %s", argv[i]);
nHeap = integerValue(argv[++i]);
}else if( strcmp(z, "no-lookaside")==0 ){
noLookaside = 1;
}else if( strcmp(z, "timeout")==0 ){
if( i==argc-1 ) fatalError("missing argument to %s", argv[i]);
iTimeout = integerValue(argv[++i]);
}else if( strcmp(z, "trace")==0 ){
runFlags |= SQL_OUTPUT|SQL_TRACE;
}else if( strcmp(z, "limit-vdbe")==0 ){
vdbeLimitFlag = 1;
}else if( strcmp(z, "v")==0 || strcmp(z, "verbose")==0 ){
verboseFlag = 1;
runFlags |= SQL_TRACE;
}else{
fatalError("unknown command-line option: \"%s\"\n", argv[i]);
}
}
if( nDb==0 ){
showHelp(argv[0]);
}
if( verboseFlag ){
sqlite3_config(SQLITE_CONFIG_LOG, sqlLog);
}
if( nHeap>0 ){
void *pHeap = malloc( nHeap );
if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap);
rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, 32);
if( rc ) fatalError("heap configuration failed: %d\n", rc);
}
if( noLookaside ){
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
}
inmemVfsRegister();
formatVfs();
StrInit(&sql);
#ifdef __unix__
signal(SIGALRM, timeoutHandler);
#endif
for(i=0; i<nDb; i++){
if( verboseFlag && nDb>1 ){
printf("DATABASE-FILE: %s\n", azDb[i]);
fflush(stdout);
}
if( iTimeout ) setAlarm(iTimeout);
createVFile("test.db", azDb[i]);
rc = sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE, "inmem");
if( rc ){
printf("cannot open test.db for \"%s\"\n", azDb[i]);
reformatVfs();
continue;
}
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( vdbeLimitFlag ){
sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag);
}
#endif
rc = sqlite3_prepare_v2(db, "SELECT sql FROM autoexec", -1, &pStmt, 0);
if( rc==SQLITE_OK ){
while( SQLITE_ROW==sqlite3_step(pStmt) ){
StrAppend(&sql, (const char*)sqlite3_column_text(pStmt, 0));
StrAppend(&sql, "\n");
}
}
sqlite3_finalize(pStmt);
StrAppend(&sql, "PRAGMA integrity_check;\n");
runSql(db, StrStr(&sql), runFlags);
sqlite3_close(db);
reformatVfs();
StrFree(&sql);
if( sqlite3_memory_used()>0 ){
free(azDb);
reformatVfs();
fatalError("memory leak of %lld bytes", sqlite3_memory_used());
}
}
StrFree(&sql);
reformatVfs();
return 0;
}
+26 -10
View File
@@ -70,7 +70,6 @@
#include <stdarg.h>
#include <ctype.h>
#include "sqlite3.h"
#include <assert.h>
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
@@ -133,6 +132,7 @@ static struct GlobalVars {
Blob *pFirstDb; /* Content of first template database */
int nSql; /* Number of SQL scripts */
Blob *pFirstSql; /* First SQL script */
unsigned int uRandom; /* Seed for the SQLite PRNG */
char zTestName[100]; /* Name of current test */
} g;
@@ -595,10 +595,18 @@ static int inmemFullPathname(
return SQLITE_OK;
}
/* Always use the same random see, for repeatability.
*/
static int inmemRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
memset(zBuf, 0, nBuf);
memcpy(zBuf, &g.uRandom, nBuf<sizeof(g.uRandom) ? nBuf : sizeof(g.uRandom));
return nBuf;
}
/*
** Register the VFS that reads from the g.aFile[] set of files.
*/
static void inmemVfsRegister(void){
static void inmemVfsRegister(int makeDefault){
static sqlite3_vfs inmemVfs;
sqlite3_vfs *pDefault = sqlite3_vfs_find(0);
inmemVfs.iVersion = 3;
@@ -609,10 +617,10 @@ static void inmemVfsRegister(void){
inmemVfs.xDelete = inmemDelete;
inmemVfs.xAccess = inmemAccess;
inmemVfs.xFullPathname = inmemFullPathname;
inmemVfs.xRandomness = pDefault->xRandomness;
inmemVfs.xRandomness = inmemRandomness;
inmemVfs.xSleep = pDefault->xSleep;
inmemVfs.xCurrentTimeInt64 = pDefault->xCurrentTimeInt64;
sqlite3_vfs_register(&inmemVfs, 0);
sqlite3_vfs_register(&inmemVfs, makeDefault);
};
/*
@@ -627,14 +635,12 @@ static void inmemVfsRegister(void){
*/
static void runSql(sqlite3 *db, const char *zSql, unsigned runFlags){
const char *zMore;
const char *zEnd = &zSql[strlen(zSql)];
sqlite3_stmt *pStmt;
while( zSql && zSql[0] ){
zMore = 0;
pStmt = 0;
sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore);
assert( zMore<=zEnd );
if( zMore==zSql ) break;
if( runFlags & SQL_TRACE ){
const char *z = zSql;
@@ -800,6 +806,7 @@ static void showHelp(void){
" -m TEXT Add a description to the database\n"
" --native-vfs Use the native VFS for initially empty database files\n"
" --oss-fuzz Enable OSS-FUZZ testing\n"
" --prng-seed N Seed value for the PRGN inside of SQLite\n"
" --rebuild Rebuild and vacuum the database file\n"
" --result-trace Show the results of each SQL command\n"
" --sqlid N Use only SQL where sqlid=N\n"
@@ -844,6 +851,7 @@ int main(int argc, char **argv){
void *pHeap = 0; /* Heap for use by SQLite */
int ossFuzz = 0; /* enable OSS-FUZZ testing */
int ossFuzzThisDb = 0; /* ossFuzz value for this particular database */
sqlite3_vfs *pDfltVfs; /* The default VFS */
iBegin = timeOfDay();
#ifdef __unix__
@@ -851,6 +859,8 @@ int main(int argc, char **argv){
#endif
g.zArgv0 = argv[0];
zFailCode = getenv("TEST_FAILURE");
pDfltVfs = sqlite3_vfs_find(0);
inmemVfsRegister(1);
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' ){
@@ -907,6 +917,10 @@ int main(int argc, char **argv){
if( strcmp(z,"oss-fuzz")==0 ){
ossFuzz = 1;
}else
if( strcmp(z,"prng-seed")==0 ){
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
g.uRandom = atoi(argv[++i]);
}else
if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
quietFlag = 1;
verboseFlag = 0;
@@ -957,7 +971,8 @@ int main(int argc, char **argv){
/* Process each source database separately */
for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){
rc = sqlite3_open(azSrcDb[iSrcDb], &db);
rc = sqlite3_open_v2(azSrcDb[iSrcDb], &db,
SQLITE_OPEN_READONLY, pDfltVfs->zName);
if( rc ){
fatalError("cannot open source database %s - %s",
azSrcDb[iSrcDb], sqlite3_errmsg(db));
@@ -1135,10 +1150,8 @@ int main(int argc, char **argv){
sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128);
}
/* Register the in-memory virtual filesystem
*/
/* Reset the in-memory virtual filesystem */
formatVfs();
inmemVfsRegister();
/* Run a test using each SQL script against each database.
*/
@@ -1163,6 +1176,7 @@ int main(int argc, char **argv){
}
}
createVFile("main.db", pDb->sz, pDb->a);
sqlite3_randomness(0,0);
if( ossFuzzThisDb ){
#ifndef SQLITE_OSS_FUZZ
fatalError("--oss-fuzz not supported: recompile with -DSQLITE_OSS_FUZZ");
@@ -1178,6 +1192,8 @@ int main(int argc, char **argv){
}
rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
if( rc ) fatalError("cannot open inmem database");
sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 100000000);
sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 50);
if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
setAlarm(iTimeout);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+56
View File
@@ -0,0 +1,56 @@
# 2016 December 30
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing OOM error handling within the built-in
# group_concat() function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix gcfault
foreach {enc} {
utf16
utf8
} {
reset_db
sqlite3_db_config_lookaside db 0 0 0
execsql "PRAGMA encoding = $enc"
do_execsql_test 1.$enc.1 {
CREATE TABLE s(i, s);
INSERT INTO s VALUES(1, ',0123456789,');
INSERT INTO s VALUES(2, X'2c303132333435363738392c');
CREATE TABLE e(e);
INSERT INTO e VALUES('v1'), ('v2');
} {}
do_faultsim_test 1.$enc.1 -faults oom* -body {
execsql { SELECT group_concat(e, (SELECT s FROM s WHERE i=1)) FROM e }
}
do_faultsim_test 1.$enc.2 -faults oom-t* -body {
execsql { SELECT group_concat(e, (SELECT s FROM s WHERE i=2)) FROM e }
}
do_faultsim_test 1.$enc.3 -faults oom-t* -prep {
set ::STMT [sqlite3_prepare db {SELECT group_concat(e, ?) FROM e} -1 dummy]
sqlite3_bind_text $::STMT 1 ",0123456789," 12
} -body {
while { "SQLITE_ROW"==[sqlite3_step $::STMT] } { }
} -test {
sqlite3_finalize $::STMT
}
}
finish_test
+9
View File
@@ -248,4 +248,13 @@ do_execsql_test instr-1.62 {
SELECT coalesce(instr(NULL,NULL), 999);
} {999}
do_execsql_test instr-1.63 {
SELECT instr(X'', 'abc')
} 0
do_execsql_test instr-1.64 {
CREATE TABLE x1(a, b);
INSERT INTO x1 VALUES(X'', 'abc');
SELECT instr(a, b) FROM x1;
} 0
finish_test
+24
View File
@@ -29,6 +29,8 @@ foreach {enc} {
utf16
} {
reset_db
sqlite3_db_config_lookaside db 0 0 0
execsql "PRAGMA encoding = $enc"
do_execsql_test 1.$enc.1 {
CREATE TABLE t1(n, h);
@@ -63,6 +65,28 @@ foreach {enc} {
faultsim_test_result {0 31}
sqlite3_finalize $::stmt
}
do_faultsim_test 1.$enc.4 -faults oom-t* -prep {
set ::stmt [sqlite3_prepare_v2 db "SELECT instr(?, ?)" -1 dummy]
sqlite3_bind_blob $::stmt 1 $::HAYSTACK [string length $::HAYSTACK]
sqlite3_bind_text $::stmt 2 $::NEEDLE [string length $::NEEDLE]
} -body {
set rc [sqlite3_step $::stmt]
if {$rc=="SQLITE_NOMEM"} { error "out of memory" }
sqlite3_column_int $::stmt 0
} -test {
faultsim_test_result {0 31}
sqlite3_finalize $::stmt
}
do_execsql_test 1.$enc.5.0 {
CREATE TABLE h1(a, b);
INSERT INTO h1 VALUES('abcdefg%200hijkl', randomblob(200));
INSERT INTO h1 SELECT b, a FROM h1;
}
do_faultsim_test 1.$enc.5 -faults oom-t* -body {
execsql { SELECT rowid FROM h1 WHERE instr(a,b) }
} -test {}
}
finish_test
+5
View File
@@ -18,6 +18,11 @@ source $testdir/tester.tcl
source $testdir/wal_common.tcl
set testprefix interrupt2
if {[permutation]=="journaltest" || [permutation]=="inmemory_journal"} {
finish_test
return
}
db close
testvfs tvfs -default 1
+583
View File
@@ -0,0 +1,583 @@
/*
** 2016-12-28
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements "key-value" performance test for SQLite. The
** purpose is to compare the speed of SQLite for accessing large BLOBs
** versus reading those same BLOB values out of individual files in the
** filesystem.
**
** Run "kvtest" with no arguments for on-line help, or see comments below.
**
** HOW TO COMPILE:
**
** (1) Gather this source file and a recent SQLite3 amalgamation with its
** header into the working directory. You should have:
**
** kvtest.c >--- this file
** sqlite3.c \___ SQLite
** sqlite3.h / amlagamation & header
**
** (2) Run you compiler against the two C source code files.
**
** (a) On linux or mac:
**
** OPTS="-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION"
** gcc -Os -I. $OPTS kvtest.c sqlite3.c -o kvtest
**
** The $OPTS options can be omitted. The $OPTS merely omit
** the need to link against -ldl and -lpthread, or whatever
** the equivalent libraries are called on your system.
**
** (b) Windows with MSVC:
**
** cl -I. kvtest.c sqlite3.c
**
** USAGE:
**
** (1) Create a test database by running "kvtest init" with appropriate
** options. See the help message for available options.
**
** (2) Construct the corresponding pile-of-files database on disk using
** the "kvtest export" command.
**
** (3) Run tests using "kvtest run" against either the SQLite database or
** the pile-of-files database and with appropriate options.
**
** For example:
**
** ./kvtest init x1.db --count 100000 --size 10000
** mkdir x1
** ./kvtest export x1.db x1
** ./kvtest run x1.db --count 10000 --max-id 1000000
** ./kvtest run x1 --count 10000 --max-id 1000000
*/
static const char zHelp[] =
"Usage: kvhelp COMMAND ARGS...\n"
"\n"
" kvhelp init DBFILE --count N --size M --pagesize X\n"
"\n"
" Generate a new test database file named DBFILE containing N\n"
" BLOBs each of size M bytes. The page size of the new database\n"
" file will be X\n"
"\n"
" kvhelp export DBFILE DIRECTORY\n"
"\n"
" Export all the blobs in the kv table of DBFILE into separate\n"
" files in DIRECTORY.\n"
"\n"
" kvhelp run DBFILE [options]\n"
"\n"
" Run a performance test. DBFILE can be either the name of a\n"
" database or a directory containing sample files. Options:\n"
"\n"
" --asc Read blobs in ascending order\n"
" --blob-api Use the BLOB API\n"
" --cache-size N Database cache size\n"
" --count N Read N blobs\n"
" --desc Read blobs in descending order\n"
" --max-id N Maximum blob key to use\n"
" --random Read blobs in a random order\n"
" --start N Start reading with this blob key\n"
;
/* Reference resources used */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <string.h>
#include "sqlite3.h"
#ifndef _WIN32
# include <unistd.h>
#else
/* Provide Windows equivalent for the needed parts of unistd.h */
# include <io.h>
# define R_OK 2
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
# define access _access
#endif
/*
** Show thqe help text and quit.
*/
static void showHelp(void){
fprintf(stdout, "%s", zHelp);
exit(1);
}
/*
** Show an error message an quit.
*/
static void fatalError(const char *zFormat, ...){
va_list ap;
fprintf(stdout, "ERROR: ");
va_start(ap, zFormat);
vfprintf(stdout, zFormat, ap);
va_end(ap);
fprintf(stdout, "\n");
exit(1);
}
/*
** Check the filesystem object zPath. Determine what it is:
**
** PATH_DIR A directory
** PATH_DB An SQLite database
** PATH_NEXIST Does not exist
** PATH_OTHER Something else
*/
#define PATH_DIR 1
#define PATH_DB 2
#define PATH_NEXIST 0
#define PATH_OTHER 99
static int pathType(const char *zPath){
struct stat x;
int rc;
if( access(zPath,R_OK) ) return PATH_NEXIST;
memset(&x, 0, sizeof(x));
rc = stat(zPath, &x);
if( rc<0 ) return PATH_OTHER;
if( S_ISDIR(x.st_mode) ) return PATH_DIR;
if( (x.st_size%512)==0 ) return PATH_DB;
return PATH_OTHER;
}
/*
** Return the size of a file in bytes. Or return -1 if the
** named object is not a regular file or does not exist.
*/
static sqlite3_int64 fileSize(const char *zPath){
struct stat x;
int rc;
memset(&x, 0, sizeof(x));
rc = stat(zPath, &x);
if( rc<0 ) return -1;
if( !S_ISREG(x.st_mode) ) return -1;
return x.st_size;
}
/*
** A Pseudo-random number generator with a fixed seed. Use this so
** that the same sequence of "random" numbers are generated on each
** run, for repeatability.
*/
static unsigned int randInt(void){
static unsigned int x = 0x333a13cd;
static unsigned int y = 0xecb2adea;
x = (x>>1) ^ ((1+~(x&1)) & 0xd0000001);
y = y*1103515245 + 12345;
return x^y;
}
/*
** Do database initialization.
*/
static int initMain(int argc, char **argv){
char *zDb;
int i, rc;
int nCount = 1000;
int sz = 10000;
int pgsz = 4096;
sqlite3 *db;
char *zSql;
char *zErrMsg = 0;
assert( strcmp(argv[1],"init")==0 );
assert( argc>=3 );
zDb = argv[2];
for(i=3; i<argc; i++){
char *z = argv[i];
if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
if( z[1]=='-' ) z++;
if( strcmp(z, "-count")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
nCount = atoi(argv[++i]);
if( nCount<1 ) fatalError("the --count must be positive");
continue;
}
if( strcmp(z, "-size")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
sz = atoi(argv[++i]);
if( sz<1 ) fatalError("the --size must be positive");
continue;
}
if( strcmp(z, "-pagesize")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
pgsz = atoi(argv[++i]);
if( pgsz<512 || pgsz>65536 || ((pgsz-1)&pgsz)!=0 ){
fatalError("the --pagesize must be power of 2 between 512 and 65536");
}
continue;
}
fatalError("unknown option: \"%s\"", argv[i]);
}
rc = sqlite3_open(zDb, &db);
if( rc ){
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
}
zSql = sqlite3_mprintf(
"DROP TABLE IF EXISTS kv;\n"
"PRAGMA page_size=%d;\n"
"VACUUM;\n"
"BEGIN;\n"
"CREATE TABLE kv(k INTEGER PRIMARY KEY, v BLOB);\n"
"WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<%d)"
" INSERT INTO kv(k,v) SELECT x, randomblob(%d) FROM c;\n"
"COMMIT;\n",
pgsz, nCount, sz
);
rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
if( rc ) fatalError("database create failed: %s", zErrMsg);
sqlite3_free(zSql);
sqlite3_close(db);
return 0;
}
/*
** Implementation of the "writefile(X,Y)" SQL function. The argument Y
** is written into file X. The number of bytes written is returned. Or
** NULL is returned if something goes wrong, such as being unable to open
** file X for writing.
*/
static void writefileFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
FILE *out;
const char *z;
sqlite3_int64 rc;
const char *zFile;
zFile = (const char*)sqlite3_value_text(argv[0]);
if( zFile==0 ) return;
out = fopen(zFile, "wb");
if( out==0 ) return;
z = (const char*)sqlite3_value_blob(argv[1]);
if( z==0 ){
rc = 0;
}else{
rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
}
fclose(out);
printf("\r%s ", zFile); fflush(stdout);
sqlite3_result_int64(context, rc);
}
/*
** Export the kv table to individual files in the filesystem
*/
static int exportMain(int argc, char **argv){
char *zDb;
char *zDir;
sqlite3 *db;
char *zSql;
int rc;
char *zErrMsg = 0;
assert( strcmp(argv[1],"export")==0 );
assert( argc>=3 );
zDb = argv[2];
if( argc!=4 ) fatalError("Usage: kvtest export DATABASE DIRECTORY");
zDir = argv[3];
if( pathType(zDir)!=PATH_DIR ){
fatalError("object \"%s\" is not a directory", zDir);
}
rc = sqlite3_open(zDb, &db);
if( rc ){
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
}
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
writefileFunc, 0, 0);
zSql = sqlite3_mprintf(
"SELECT writefile(printf('%s/%%06d',k),v) FROM kv;",
zDir
);
rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
if( rc ) fatalError("database create failed: %s", zErrMsg);
sqlite3_free(zSql);
sqlite3_close(db);
printf("\n");
return 0;
}
/*
** Read the content of file zName into memory obtained from sqlite3_malloc64()
** and return a pointer to the buffer. The caller is responsible for freeing
** the memory.
**
** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
** read.
**
** For convenience, a nul-terminator byte is always appended to the data read
** from the file before the buffer is returned. This byte is not included in
** the final value of (*pnByte), if applicable.
**
** NULL is returned if any error is encountered. The final value of *pnByte
** is undefined in this case.
*/
static unsigned char *readFile(const char *zName, int *pnByte){
FILE *in; /* FILE from which to read content of zName */
sqlite3_int64 nIn; /* Size of zName in bytes */
size_t nRead; /* Number of bytes actually read */
unsigned char *pBuf; /* Content read from disk */
nIn = fileSize(zName);
if( nIn<0 ) return 0;
in = fopen(zName, "rb");
if( in==0 ) return 0;
pBuf = sqlite3_malloc64( nIn );
if( pBuf==0 ) return 0;
nRead = fread(pBuf, nIn, 1, in);
fclose(in);
if( nRead!=1 ){
sqlite3_free(pBuf);
return 0;
}
if( pnByte ) *pnByte = nIn;
return pBuf;
}
/*
** Return the current time in milliseconds since the beginning of
** the Julian epoch.
*/
static sqlite3_int64 timeOfDay(void){
static sqlite3_vfs *clockVfs = 0;
sqlite3_int64 t;
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
clockVfs->xCurrentTimeInt64(clockVfs, &t);
}else{
double r;
clockVfs->xCurrentTime(clockVfs, &r);
t = (sqlite3_int64)(r*86400000.0);
}
return t;
}
/* Blob access order */
#define ORDER_ASC 1
#define ORDER_DESC 2
#define ORDER_RANDOM 3
/*
** Run a performance test
*/
static int runMain(int argc, char **argv){
int eType; /* Is zDb a database or a directory? */
char *zDb; /* Database or directory name */
int i; /* Loop counter */
int rc; /* Return code from SQLite calls */
int nCount = 1000; /* Number of blob fetch operations */
int nExtra = 0; /* Extra cycles */
int iKey = 1; /* Next blob key */
int iMax = 1000; /* Largest allowed key */
int iPagesize = 0; /* Database page size */
int iCache = 1000; /* Database cache size in kibibytes */
int bBlobApi = 0; /* Use the incremental blob I/O API */
int eOrder = ORDER_ASC; /* Access order */
sqlite3 *db = 0; /* Database connection */
sqlite3_stmt *pStmt = 0; /* Prepared statement for SQL access */
sqlite3_blob *pBlob = 0; /* Handle for incremental Blob I/O */
sqlite3_int64 tmStart; /* Start time */
sqlite3_int64 tmElapsed; /* Elapsed time */
int nData = 0; /* Bytes of data */
sqlite3_int64 nTotal = 0; /* Total data read */
unsigned char *pData; /* Content of the blob */
assert( strcmp(argv[1],"run")==0 );
assert( argc>=3 );
zDb = argv[2];
eType = pathType(zDb);
if( eType==PATH_OTHER ) fatalError("unknown object type: \"%s\"", zDb);
if( eType==PATH_NEXIST ) fatalError("object does not exist: \"%s\"", zDb);
for(i=3; i<argc; i++){
char *z = argv[i];
if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
if( z[1]=='-' ) z++;
if( strcmp(z, "-count")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
nCount = atoi(argv[++i]);
if( nCount<1 ) fatalError("the --count must be positive");
continue;
}
if( strcmp(z, "-max-id")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iMax = atoi(argv[++i]);
if( iMax<1 ) fatalError("the --max-id must be positive");
continue;
}
if( strcmp(z, "-start")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iKey = atoi(argv[++i]);
if( iKey<1 ) fatalError("the --start must be positive");
continue;
}
if( strcmp(z, "-cache-size")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iCache = atoi(argv[++i]);
continue;
}
if( strcmp(z, "-random")==0 ){
eOrder = ORDER_RANDOM;
continue;
}
if( strcmp(z, "-asc")==0 ){
eOrder = ORDER_ASC;
continue;
}
if( strcmp(z, "-desc")==0 ){
eOrder = ORDER_DESC;
continue;
}
if( strcmp(z, "-blob-api")==0 ){
bBlobApi = 1;
continue;
}
fatalError("unknown option: \"%s\"", argv[i]);
}
tmStart = timeOfDay();
if( eType==PATH_DB ){
char *zSql;
rc = sqlite3_open(zDb, &db);
if( rc ){
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
}
zSql = sqlite3_mprintf("PRAGMA cache_size=%d", iCache);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
pStmt = 0;
sqlite3_prepare_v2(db, "PRAGMA page_size", -1, &pStmt, 0);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
iPagesize = sqlite3_column_int(pStmt, 0);
}
sqlite3_finalize(pStmt);
sqlite3_prepare_v2(db, "PRAGMA cache_size", -1, &pStmt, 0);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
iCache = sqlite3_column_int(pStmt, 0);
}else{
iCache = 0;
}
sqlite3_finalize(pStmt);
pStmt = 0;
sqlite3_exec(db, "BEGIN", 0, 0, 0);
}
for(i=0; i<nCount; i++){
if( eType==PATH_DIR ){
/* CASE 1: Reading blobs out of separate files */
char *zKey;
zKey = sqlite3_mprintf("%s/%06d", zDb, iKey);
nData = 0;
pData = readFile(zKey, &nData);
sqlite3_free(zKey);
sqlite3_free(pData);
}else if( bBlobApi ){
/* CASE 2: Reading from database using the incremental BLOB I/O API */
if( pBlob==0 ){
rc = sqlite3_blob_open(db, "main", "kv", "v", iKey, 0, &pBlob);
if( rc ){
fatalError("could not open sqlite3_blob handle: %s",
sqlite3_errmsg(db));
}
}else{
rc = sqlite3_blob_reopen(pBlob, iKey);
}
if( rc==SQLITE_OK ){
nData = sqlite3_blob_bytes(pBlob);
pData = sqlite3_malloc( nData+1 );
if( pData==0 ) fatalError("cannot allocate %d bytes", nData+1);
rc = sqlite3_blob_read(pBlob, pData, nData, 0);
if( rc!=SQLITE_OK ){
fatalError("could not read the blob at %d: %s", iKey,
sqlite3_errmsg(db));
}
sqlite3_free(pData);
}
}else{
/* CASE 3: Reading from database using SQL */
if( pStmt==0 ){
rc = sqlite3_prepare_v2(db,
"SELECT v FROM kv WHERE k=?1", -1, &pStmt, 0);
if( rc ){
fatalError("cannot prepare query: %s", sqlite3_errmsg(db));
}
}else{
sqlite3_reset(pStmt);
}
sqlite3_bind_int(pStmt, 1, iKey);
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
nData = sqlite3_column_bytes(pStmt, 0);
pData = (unsigned char*)sqlite3_column_blob(pStmt, 0);
}else{
nData = 0;
}
}
if( eOrder==ORDER_ASC ){
iKey++;
if( iKey>iMax ) iKey = 1;
}else if( eOrder==ORDER_DESC ){
iKey--;
if( iKey<=0 ) iKey = iMax;
}else{
iKey = (randInt()%iMax)+1;
}
nTotal += nData;
if( nData==0 ){ nCount++; nExtra++; }
}
if( pStmt ) sqlite3_finalize(pStmt);
if( pBlob ) sqlite3_blob_close(pBlob);
if( db ) sqlite3_close(db);
tmElapsed = timeOfDay() - tmStart;
if( nExtra ){
printf("%d cycles due to %d misses\n", nCount, nExtra);
}
if( eType==PATH_DB ){
printf("SQLite version: %s\n", sqlite3_libversion());
}
printf("--count %d --max-id %d", nCount-nExtra, iMax);
if( eType==PATH_DB ){
printf(" --cache-size %d", iCache);
}
switch( eOrder ){
case ORDER_RANDOM: printf(" --random\n"); break;
case ORDER_DESC: printf(" --desc\n"); break;
default: printf(" --asc\n"); break;
}
if( iPagesize ) printf("Database page size: %d\n", iPagesize);
printf("Total elapsed time: %.3f\n", tmElapsed/1000.0);
printf("Microseconds per BLOB read: %.3f\n", tmElapsed*1000.0/nCount);
printf("Content read rate: %.1f MB/s\n", nTotal/(1000.0*tmElapsed));
return 0;
}
int main(int argc, char **argv){
if( argc<3 ) showHelp();
if( strcmp(argv[1],"init")==0 ){
return initMain(argc, argv);
}
if( strcmp(argv[1],"export")==0 ){
return exportMain(argc, argv);
}
if( strcmp(argv[1],"run")==0 ){
return runMain(argc, argv);
}
showHelp();
return 0;
}
+5
View File
@@ -19,10 +19,15 @@ source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
if {[permutation]=="journaltest" || [permutation]=="inmemory_journal"} {
finish_test
return
}
set testprefix nockpt
do_execsql_test 1.0 {
PRAGMA auto_vacuum=OFF;
PRAGMA page_size = 1024;
PRAGMA journal_mode = wal;
CREATE TABLE c1(x, y, z);
+4
View File
@@ -6,12 +6,14 @@
#include <stdint.h>
#include "sqlite3.h"
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
** Progress handler callback
*/
static int progress_handler(void *pReturn) {
return *(int*)pReturn;
}
#endif
/*
** Callback for sqlite3_exec().
@@ -53,11 +55,13 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
if( rc ) return 0;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Bit 0 of the selector enables progress callbacks. Bit 1 is the
** return code from progress callbacks */
if( uSelector & 1 ){
sqlite3_progress_handler(db, 4, progress_handler, (void*)&progressArg);
}
#endif
uSelector >>= 1;
progressArg = uSelector & 1; uSelector >>= 1;
+78
View File
@@ -315,5 +315,83 @@ foreach {tn n sql} {
do_catchsql_test 14.2.$tn $sql [list 1 $err]
}
#--------------------------------------------------------------------------
# Test for vector size mismatches concealed by unexpanded subqueries.
#
do_catchsql_test 15.1 {
DETACH (SELECT * FROM (SELECT 1,2))<3;
} {1 {row value misused}}
do_catchsql_test 15.2 {
UPDATE x1 SET a=(SELECT * FROM (SELECT b,2))<3;
} {1 {row value misused}}
do_catchsql_test 15.3 {
UPDATE x1 SET a=NULL WHERE a<(SELECT * FROM (SELECT b,2));
} {1 {sub-select returns 2 columns - expected 1}}
do_catchsql_test 15.4 {
DELETE FROM x1 WHERE a<(SELECT * FROM (SELECT b,2));
} {1 {sub-select returns 2 columns - expected 1}}
do_catchsql_test 15.5 {
INSERT INTO x1(a,b) VALUES(1,(SELECT * FROM (SELECT 1,2))<3);
} {1 {row value misused}}
#-------------------------------------------------------------------------
# Row-values used in UPDATE statements within TRIGGERs
#
# Ticket https://www.sqlite.org/src/info/8c9458e703666e1a
#
do_execsql_test 16.1 {
CREATE TABLE t16a(a,b,c);
INSERT INTO t16a VALUES(1,2,3);
CREATE TABLE t16b(x);
INSERT INTO t16b(x) VALUES(1);
CREATE TRIGGER t16r AFTER UPDATE ON t16b BEGIN
UPDATE t16a SET (a,b,c)=(SELECT new.x,new.x+1,new.x+2);
END;
UPDATE t16b SET x=7;
SELECT * FROM t16a;
} {7 8 9}
do_execsql_test 16.2 {
UPDATE t16b SET x=97;
SELECT * FROM t16a;
} {97 98 99}
do_execsql_test 16.3 {
CREATE TABLE t16c(a, b, c, d, e);
INSERT INTO t16c VALUES(1, 'a', 'b', 'c', 'd');
CREATE TRIGGER t16c1 AFTER INSERT ON t16c BEGIN
UPDATE t16c SET (c, d) = (SELECT 'A', 'B'), (e, b) = (SELECT 'C', 'D')
WHERE a = new.a-1;
END;
SELECT * FROM t16c;
} {1 a b c d}
do_execsql_test 16.4 {
INSERT INTO t16c VALUES(2, 'w', 'x', 'y', 'z');
SELECT * FROM t16c;
} {
1 D A B C
2 w x y z
}
do_execsql_test 16.5 {
DROP TRIGGER t16c1;
PRAGMA recursive_triggers = 1;
INSERT INTO t16c VALUES(3, 'i', 'ii', 'iii', 'iv');
CREATE TRIGGER t16c1 AFTER UPDATE ON t16c WHEN new.a>1 BEGIN
UPDATE t16c SET (e, d) = (
SELECT b, c FROM t16c WHERE a = new.a-1
), (c, b) = (
SELECT d, e FROM t16c WHERE a = new.a-1
) WHERE a = new.a-1;
END;
UPDATE t16c SET a=a WHERE a=3;
SELECT * FROM t16c;
} {
1 C B A D
2 z y x w
3 i ii iii iv
}
finish_test
+2
View File
@@ -273,6 +273,7 @@ do_test shell1-3.2.4 {
catchcmd "test.db" ".bail OFF BAD"
} {1 {Usage: .bail on|off}}
ifcapable vtab {
# .databases List names and files of attached databases
do_test shell1-3.3.1 {
catchcmd "-csv test.db" ".databases"
@@ -281,6 +282,7 @@ do_test shell1-3.3.2 {
# extra arguments ignored
catchcmd "test.db" ".databases BAD"
} "/0.+main.+[string map {/ ".{1,2}"} [string range [get_pwd] 0 10]].*/"
}
# .dump ?TABLE? ... Dump the database in an SQL text format
# If TABLE specified, only dump tables matching
+3 -2
View File
@@ -9,9 +9,12 @@
#
#***********************************************************************
#
# Test the shell tool ".lint fkey-indexes" command.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !vtab {finish_test; return}
set testprefix shell6
set CLI [test_find_cli]
db close
@@ -96,5 +99,3 @@ foreach {tn schema output} {
}
finish_test
+54
View File
@@ -0,0 +1,54 @@
# 2016 December 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Test the readfile() function built into the shell tool. Specifically,
# that it does not truncate the blob read at the first embedded 0x00
# byte.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix shell7
set CLI [test_find_cli]
do_execsql_test 1.0 {
CREATE TABLE f1(tn INTEGER PRIMARY KEY, x BLOB);
CREATE TABLE f2(tn INTEGER PRIMARY KEY, x BLOB);
INSERT INTO f1 VALUES(1, X'01020304');
INSERT INTO f1 VALUES(2, X'01000304');
INSERT INTO f1 VALUES(3, randomblob(200));
}
foreach {tn l x} [db eval { SELECT tn, length(x) AS l, x FROM f1 }] {
forcedelete shell7_test.bin
set fd [open shell7_test.bin w]
fconfigure $fd -encoding binary
fconfigure $fd -translation binary
puts -nonewline $fd $x
close $fd
do_test 1.$tn.1 { file size shell7_test.bin } $l
do_test 1.$tn.2 {
catchcmd test.db "INSERT INTO f2 VALUES($tn, readfile('shell7_test.bin'));"
} {0 {}}
do_execsql_test 1.$tn.3 {
SELECT (SELECT x FROM f1 WHERE tn=1)==(SELECT x FROM f2 WHERE tn=1)
} {1}
}
finish_test
+7 -3
View File
@@ -50,7 +50,11 @@ static const char zHelp[] =
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#ifndef _WIN32
# include <unistd.h>
#else
# include <io.h>
#endif
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
@@ -1374,7 +1378,7 @@ int main(int argc, char **argv){
int doIncrvac = 0; /* True for --incrvacuum */
const char *zJMode = 0; /* Journal mode */
const char *zKey = 0; /* Encryption key */
int nLook = 0, szLook = 0; /* --lookaside configuration */
int nLook = -1, szLook = 0; /* --lookaside configuration */
int noSync = 0; /* True for --nosync */
int pageSize = 0; /* Desired page size. 0 means default */
int nPCache = 0, szPCache = 0;/* --pcache configuration */
@@ -1558,7 +1562,7 @@ int main(int argc, char **argv){
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
if( rc ) fatal_error("scratch configuration failed: %d\n", rc);
}
if( nLook>0 ){
if( nLook>=0 ){
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
}
#endif
+56
View File
@@ -61,4 +61,60 @@ do_execsql_test 2.1 {
SELECT * FROM t1;
} {200}
#-------------------------------------------------------------------------
# Test that the planner notices LIMIT clauses on recursive WITH queries.
#
ifcapable analyze {
do_execsql_test 3.1.1 {
CREATE TABLE y1(a, b);
CREATE INDEX y1a ON y1(a);
WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000)
INSERT INTO y1 SELECT i%10, i FROM cnt;
ANALYZE;
}
do_eqp_test 3.1.2 {
WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1)
SELECT * FROM cnt, y1 WHERE i=a
} {
3 0 0 {SCAN TABLE cnt}
1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
0 0 0 {SCAN SUBQUERY 1}
0 1 1 {SEARCH TABLE y1 USING INDEX y1a (a=?)}
}
do_eqp_test 3.1.3 {
WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000000)
SELECT * FROM cnt, y1 WHERE i=a
} {
3 0 0 {SCAN TABLE cnt}
1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
0 0 1 {SCAN TABLE y1}
0 1 0 {SEARCH SUBQUERY 1 USING AUTOMATIC COVERING INDEX (i=?)}
}
}
do_execsql_test 3.2.1 {
CREATE TABLE w1(pk INTEGER PRIMARY KEY, x INTEGER);
CREATE TABLE w2(pk INTEGER PRIMARY KEY);
}
do_eqp_test 3.2.2 {
WITH RECURSIVE c(w,id) AS (SELECT 0, (SELECT pk FROM w2 LIMIT 1)
UNION ALL SELECT c.w + 1, x FROM w1, c LIMIT 1)
SELECT * FROM c, w2, w1
WHERE c.id=w2.pk AND c.id=w1.pk;
} {
2 0 0 {EXECUTE SCALAR SUBQUERY 3}
3 0 0 {SCAN TABLE w2}
4 0 0 {SCAN TABLE w1}
4 1 1 {SCAN TABLE c}
1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)} 0 0 0 {SCAN SUBQUERY 1}
0 1 1 {SEARCH TABLE w2 USING INTEGER PRIMARY KEY (rowid=?)}
0 2 2 {SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?)}
}
finish_test
+282 -190
View File
@@ -13,24 +13,6 @@
**
** Option:
**
** --without-rowid Use a WITHOUT ROWID table to store the words.
** --insert Use INSERT mode (the default)
** --replace Use REPLACE mode
** --select Use SELECT mode
** --update Use UPDATE mode
** --delete Use DELETE mode
** --query Use QUERY mode
** --nocase Add the NOCASE collating sequence to the words.
** --trace Enable sqlite3_trace() output.
** --summary Show summary information on the collected data.
** --stats Show sqlite3_status() results at the end.
** --pagesize NNN Use a page size of NNN
** --cachesize NNN Use a cache size of NNN
** --commit NNN Commit after every NNN operations
** --nosync Use PRAGMA synchronous=OFF
** --journal MMMM Use PRAGMA journal_mode=MMMM
** --timer Time the operation of this program
** --tag NAME Tag all output using NAME. Use only stdout.
**
** Modes:
**
@@ -81,8 +63,36 @@
#include <stdlib.h>
#include <stdarg.h>
#include "sqlite3.h"
#ifndef _WIN32
# include <unistd.h>
#else
# include <io.h>
#endif
#define ISALPHA(X) isalpha((unsigned char)(X))
const char zHelp[] =
"Usage: wordcount [OPTIONS] DATABASE [INPUT]\n"
" --all Repeat the test for all test modes\n"
" --cachesize NNN Use a cache size of NNN\n"
" --commit NNN Commit after every NNN operations\n"
" --delete Use DELETE mode\n"
" --insert Use INSERT mode (the default)\n"
" --journal MMMM Use PRAGMA journal_mode=MMMM\n"
" --nocase Add the NOCASE collating sequence to the words.\n"
" --nosync Use PRAGMA synchronous=OFF\n"
" --pagesize NNN Use a page size of NNN\n"
" --query Use QUERY mode\n"
" --replace Use REPLACE mode\n"
" --select Use SELECT mode\n"
" --stats Show sqlite3_status() results at the end.\n"
" --summary Show summary information on the collected data.\n"
" --tag NAME Tag all output using NAME. Use only stdout.\n"
" --timer Time the operation of this program\n"
" --trace Enable sqlite3_trace() output.\n"
" --update Use UPDATE mode\n"
" --without-rowid Use a WITHOUT ROWID table to store the words.\n"
;
/* Output tag */
char *zTag = "--";
@@ -110,6 +120,12 @@ static void fatal_error(const char *zMsg, ...){
exit(1);
}
/* Print a usage message and quit */
static void usage(void){
printf("%s",zHelp);
exit(0);
}
/* The sqlite3_trace() callback function */
static void traceCallback(void *NotUsed, const char *zSql){
printf("%s;\n", zSql);
@@ -189,7 +205,6 @@ static void checksumFinalize(sqlite3_context *context){
}
}
/* Define operating modes */
#define MODE_INSERT 0
#define MODE_REPLACE 1
@@ -197,12 +212,50 @@ static void checksumFinalize(sqlite3_context *context){
#define MODE_UPDATE 3
#define MODE_DELETE 4
#define MODE_QUERY 5
#define MODE_COUNT 6
#define MODE_ALL (-1)
/* Mode names */
static const char *azMode[] = {
"--insert",
"--replace",
"--select",
"--update",
"--delete",
"--query"
};
/*
** Determine if another iteration of the test is required. Return true
** if so. Return zero if all iterations have finished.
*/
static int allLoop(
int iMode, /* The selected test mode */
int *piLoopCnt, /* Iteration loop counter */
int *piMode2, /* The test mode to use on the next iteration */
int *pUseWithoutRowid /* Whether or not to use --without-rowid */
){
int i;
if( iMode!=MODE_ALL ){
if( *piLoopCnt ) return 0;
*piMode2 = iMode;
*piLoopCnt = 1;
return 1;
}
if( (*piLoopCnt)>=MODE_COUNT*2 ) return 0;
i = (*piLoopCnt)++;
*pUseWithoutRowid = i&1;
*piMode2 = i>>1;
return 1;
}
int main(int argc, char **argv){
const char *zFileToRead = 0; /* Input file. NULL for stdin */
const char *zDbName = 0; /* Name of the database file to create */
int useWithoutRowid = 0; /* True for --without-rowid */
int iMode = MODE_INSERT; /* One of MODE_xxxxx */
int iMode2; /* Mode to use for current --all iteration */
int iLoopCnt = 0; /* Which iteration when running --all */
int useNocase = 0; /* True for --nocase */
int doTrace = 0; /* True for --trace */
int showStats = 0; /* True for --stats */
@@ -226,7 +279,8 @@ int main(int argc, char **argv){
int iCur, iHiwtr; /* Statistics values, current and "highwater" */
FILE *pTimer = stderr; /* Output channel for the timer */
sqlite3_int64 sumCnt = 0; /* Sum in QUERY mode */
sqlite3_int64 startTime;
sqlite3_int64 startTime; /* Time of start */
sqlite3_int64 totalTime = 0; /* Total time */
char zInput[2000]; /* A single line of input */
/* Process command-line arguments */
@@ -248,6 +302,9 @@ int main(int argc, char **argv){
iMode = MODE_DELETE;
}else if( strcmp(z,"query")==0 ){
iMode = MODE_QUERY;
}else if( strcmp(z,"all")==0 ){
iMode = MODE_ALL;
showTimer = -99;
}else if( strcmp(z,"nocase")==0 ){
useNocase = 1;
}else if( strcmp(z,"trace")==0 ){
@@ -274,23 +331,30 @@ int main(int argc, char **argv){
}else if( strcmp(z,"tag")==0 && i<argc-1 ){
zTag = argv[++i];
pTimer = stdout;
}else if( strcmp(z, "help")==0 || strcmp(z,"?")==0 ){
usage();
}else{
fatal_error("unknown option: %s\n", argv[i]);
fatal_error("unknown option: \"%s\"\n"
"Use --help for a list of options\n",
argv[i]);
}
}else if( zDbName==0 ){
zDbName = argv[i];
}else if( zFileToRead==0 ){
zFileToRead = argv[i];
}else{
fatal_error("surplus argument: %s\n", argv[i]);
fatal_error("surplus argument: \"%s\"\n", argv[i]);
}
}
if( zDbName==0 ){
fatal_error("Usage: %s [--options] DATABASE [INPUTFILE]\n", argv[0]);
usage();
}
startTime = realTime();
/* Open the database and the input file */
if( zDbName[0] && strcmp(zDbName,":memory:")!=0 ){
unlink(zDbName);
}
if( sqlite3_open(zDbName, &db) ){
fatal_error("Cannot open database file: %s\n", zDbName);
}
@@ -300,6 +364,9 @@ int main(int argc, char **argv){
fatal_error("Could not open input file \"%s\"\n", zFileToRead);
}
}else{
if( iMode==MODE_ALL ){
fatal_error("The --all mode cannot be used with stdin\n");
}
in = stdin;
}
@@ -322,189 +389,214 @@ int main(int argc, char **argv){
sqlite3_free(zSql);
}
/* Construct the "wordcount" table into which to put the words */
if( sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, 0) ){
fatal_error("Could not start a transaction\n");
}
zSql = sqlite3_mprintf(
"CREATE TABLE IF NOT EXISTS wordcount(\n"
" word TEXT PRIMARY KEY COLLATE %s,\n"
" cnt INTEGER\n"
")%s",
useNocase ? "nocase" : "binary",
useWithoutRowid ? " WITHOUT ROWID" : ""
);
if( zSql==0 ) fatal_error("out of memory\n");
rc = sqlite3_exec(db, zSql, 0, 0, 0);
if( rc ) fatal_error("Could not create the wordcount table: %s.\n",
sqlite3_errmsg(db));
sqlite3_free(zSql);
/* Prepare SQL statements that will be needed */
if( iMode==MODE_QUERY ){
rc = sqlite3_prepare_v2(db,
"SELECT cnt FROM wordcount WHERE word=?1",
-1, &pSelect, 0);
if( rc ) fatal_error("Could not prepare the SELECT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_SELECT ){
rc = sqlite3_prepare_v2(db,
"SELECT 1 FROM wordcount WHERE word=?1",
-1, &pSelect, 0);
if( rc ) fatal_error("Could not prepare the SELECT statement: %s\n",
sqlite3_errmsg(db));
rc = sqlite3_prepare_v2(db,
"INSERT INTO wordcount(word,cnt) VALUES(?1,1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
iLoopCnt = 0;
while( allLoop(iMode, &iLoopCnt, &iMode2, &useWithoutRowid) ){
/* Delete prior content in --all mode */
if( iMode==MODE_ALL ){
if( sqlite3_exec(db, "DROP TABLE IF EXISTS wordcount; VACUUM;",0,0,0) ){
fatal_error("Could not clean up prior iteration\n");
}
startTime = realTime();
rewind(in);
}
/* Construct the "wordcount" table into which to put the words */
if( sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, 0) ){
fatal_error("Could not start a transaction\n");
}
zSql = sqlite3_mprintf(
"CREATE TABLE IF NOT EXISTS wordcount(\n"
" word TEXT PRIMARY KEY COLLATE %s,\n"
" cnt INTEGER\n"
")%s",
useNocase ? "nocase" : "binary",
useWithoutRowid ? " WITHOUT ROWID" : ""
);
if( zSql==0 ) fatal_error("out of memory\n");
rc = sqlite3_exec(db, zSql, 0, 0, 0);
if( rc ) fatal_error("Could not create the wordcount table: %s.\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_SELECT || iMode==MODE_UPDATE || iMode==MODE_INSERT ){
rc = sqlite3_prepare_v2(db,
"UPDATE wordcount SET cnt=cnt+1 WHERE word=?1",
-1, &pUpdate, 0);
if( rc ) fatal_error("Could not prepare the UPDATE statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_INSERT ){
rc = sqlite3_prepare_v2(db,
"INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_UPDATE ){
rc = sqlite3_prepare_v2(db,
"INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,0)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_REPLACE ){
rc = sqlite3_prepare_v2(db,
sqlite3_free(zSql);
/* Prepare SQL statements that will be needed */
if( iMode2==MODE_QUERY ){
rc = sqlite3_prepare_v2(db,
"SELECT cnt FROM wordcount WHERE word=?1",
-1, &pSelect, 0);
if( rc ) fatal_error("Could not prepare the SELECT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_SELECT ){
rc = sqlite3_prepare_v2(db,
"SELECT 1 FROM wordcount WHERE word=?1",
-1, &pSelect, 0);
if( rc ) fatal_error("Could not prepare the SELECT statement: %s\n",
sqlite3_errmsg(db));
rc = sqlite3_prepare_v2(db,
"INSERT INTO wordcount(word,cnt) VALUES(?1,1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_SELECT || iMode2==MODE_UPDATE || iMode2==MODE_INSERT ){
rc = sqlite3_prepare_v2(db,
"UPDATE wordcount SET cnt=cnt+1 WHERE word=?1",
-1, &pUpdate, 0);
if( rc ) fatal_error("Could not prepare the UPDATE statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_INSERT ){
rc = sqlite3_prepare_v2(db,
"INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_UPDATE ){
rc = sqlite3_prepare_v2(db,
"INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,0)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_REPLACE ){
rc = sqlite3_prepare_v2(db,
"REPLACE INTO wordcount(word,cnt)"
"VALUES(?1,coalesce((SELECT cnt FROM wordcount WHERE word=?1),0)+1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the REPLACE statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_DELETE ){
rc = sqlite3_prepare_v2(db,
"DELETE FROM wordcount WHERE word=?1",
-1, &pDelete, 0);
if( rc ) fatal_error("Could not prepare the DELETE statement: %s\n",
sqlite3_errmsg(db));
}
/* Process the input file */
while( fgets(zInput, sizeof(zInput), in) ){
for(i=0; zInput[i]; i++){
if( !ISALPHA(zInput[i]) ) continue;
for(j=i+1; ISALPHA(zInput[j]); j++){}
/* Found a new word at zInput[i] that is j-i bytes long.
** Process it into the wordcount table. */
if( iMode==MODE_DELETE ){
sqlite3_bind_text(pDelete, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pDelete)!=SQLITE_DONE ){
fatal_error("DELETE failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pDelete);
}else if( iMode==MODE_SELECT ){
sqlite3_bind_text(pSelect, 1, zInput+i, j-i, SQLITE_STATIC);
rc = sqlite3_step(pSelect);
sqlite3_reset(pSelect);
if( rc==SQLITE_ROW ){
sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
if( rc ) fatal_error("Could not prepare the REPLACE statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_DELETE ){
rc = sqlite3_prepare_v2(db,
"DELETE FROM wordcount WHERE word=?1",
-1, &pDelete, 0);
if( rc ) fatal_error("Could not prepare the DELETE statement: %s\n",
sqlite3_errmsg(db));
}
/* Process the input file */
while( fgets(zInput, sizeof(zInput), in) ){
for(i=0; zInput[i]; i++){
if( !ISALPHA(zInput[i]) ) continue;
for(j=i+1; ISALPHA(zInput[j]); j++){}
/* Found a new word at zInput[i] that is j-i bytes long.
** Process it into the wordcount table. */
if( iMode2==MODE_DELETE ){
sqlite3_bind_text(pDelete, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pDelete)!=SQLITE_DONE ){
fatal_error("DELETE failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pUpdate);
}else if( rc==SQLITE_DONE ){
sqlite3_reset(pDelete);
}else if( iMode2==MODE_SELECT ){
sqlite3_bind_text(pSelect, 1, zInput+i, j-i, SQLITE_STATIC);
rc = sqlite3_step(pSelect);
sqlite3_reset(pSelect);
if( rc==SQLITE_ROW ){
sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pUpdate);
}else if( rc==SQLITE_DONE ){
sqlite3_bind_text(pInsert, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pInsert)!=SQLITE_DONE ){
fatal_error("Insert failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pInsert);
}else{
fatal_error("SELECT failed: %s\n", sqlite3_errmsg(db));
}
}else if( iMode2==MODE_QUERY ){
sqlite3_bind_text(pSelect, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pSelect)==SQLITE_ROW ){
sumCnt += sqlite3_column_int64(pSelect, 0);
}
sqlite3_reset(pSelect);
}else{
sqlite3_bind_text(pInsert, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pInsert)!=SQLITE_DONE ){
fatal_error("Insert failed: %s\n", sqlite3_errmsg(db));
fatal_error("INSERT failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pInsert);
}else{
fatal_error("SELECT failed: %s\n", sqlite3_errmsg(db));
}
}else if( iMode==MODE_QUERY ){
sqlite3_bind_text(pSelect, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pSelect)==SQLITE_ROW ){
sumCnt += sqlite3_column_int64(pSelect, 0);
}
sqlite3_reset(pSelect);
}else{
sqlite3_bind_text(pInsert, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pInsert)!=SQLITE_DONE ){
fatal_error("INSERT failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pInsert);
if( iMode==MODE_UPDATE
|| (iMode==MODE_INSERT && sqlite3_changes(db)==0)
){
sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
if( iMode2==MODE_UPDATE
|| (iMode2==MODE_INSERT && sqlite3_changes(db)==0)
){
sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pUpdate);
}
sqlite3_reset(pUpdate);
}
i = j-1;
/* Increment the operation counter. Do a COMMIT if it is time. */
nOp++;
if( commitInterval>0 && (nOp%commitInterval)==0 ){
sqlite3_exec(db, "COMMIT; BEGIN IMMEDIATE", 0, 0, 0);
}
}
i = j-1;
/* Increment the operation counter. Do a COMMIT if it is time. */
nOp++;
if( commitInterval>0 && (nOp%commitInterval)==0 ){
sqlite3_exec(db, "COMMIT; BEGIN IMMEDIATE", 0, 0, 0);
}
sqlite3_exec(db, "COMMIT", 0, 0, 0);
sqlite3_finalize(pInsert); pInsert = 0;
sqlite3_finalize(pUpdate); pUpdate = 0;
sqlite3_finalize(pSelect); pSelect = 0;
sqlite3_finalize(pDelete); pDelete = 0;
if( iMode2==MODE_QUERY && iMode!=MODE_ALL ){
printf("%s sum of cnt: %lld\n", zTag, sumCnt);
rc = sqlite3_prepare_v2(db,"SELECT sum(cnt*cnt) FROM wordcount", -1,
&pSelect, 0);
if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
printf("%s double-check: %lld\n", zTag,sqlite3_column_int64(pSelect,0));
}
sqlite3_finalize(pSelect);
}
if( showTimer ){
sqlite3_int64 elapseTime = realTime() - startTime;
totalTime += elapseTime;
fprintf(pTimer, "%3d.%03d wordcount", (int)(elapseTime/1000),
(int)(elapseTime%1000));
if( iMode==MODE_ALL ){
fprintf(pTimer, " %s%s\n", azMode[iMode2],
useWithoutRowid? " --without-rowid" : "");
}else{
for(i=1; i<argc; i++) if( i!=showTimer ) fprintf(pTimer," %s",argv[i]);
fprintf(pTimer, "\n");
}
}
}
sqlite3_exec(db, "COMMIT", 0, 0, 0);
if( zFileToRead ) fclose(in);
sqlite3_finalize(pInsert);
sqlite3_finalize(pUpdate);
sqlite3_finalize(pSelect);
sqlite3_finalize(pDelete);
if( iMode==MODE_QUERY ){
printf("%s sum of cnt: %lld\n", zTag, sumCnt);
rc = sqlite3_prepare_v2(db,"SELECT sum(cnt*cnt) FROM wordcount", -1,
&pSelect, 0);
if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
printf("%s double-check: %lld\n", zTag, sqlite3_column_int64(pSelect, 0));
if( showSummary ){
sqlite3_create_function(db, "checksum", -1, SQLITE_UTF8, 0,
0, checksumStep, checksumFinalize);
sqlite3_exec(db,
"SELECT 'count(*): ', count(*) FROM wordcount;\n"
"SELECT 'sum(cnt): ', sum(cnt) FROM wordcount;\n"
"SELECT 'max(cnt): ', max(cnt) FROM wordcount;\n"
"SELECT 'avg(cnt): ', avg(cnt) FROM wordcount;\n"
"SELECT 'sum(cnt=1):', sum(cnt=1) FROM wordcount;\n"
"SELECT 'top 10: ', group_concat(word, ', ') FROM "
"(SELECT word FROM wordcount ORDER BY cnt DESC, word LIMIT 10);\n"
"SELECT 'checksum: ', checksum(word, cnt) FROM "
"(SELECT word, cnt FROM wordcount ORDER BY word);\n"
"PRAGMA integrity_check;\n",
printResult, 0, 0);
}
sqlite3_finalize(pSelect);
} /* End the --all loop */
/* Close the input file after the last read */
if( zFileToRead ) fclose(in);
/* In --all mode, so the total time */
if( iMode==MODE_ALL && showTimer ){
fprintf(pTimer, "%3d.%03d wordcount --all\n", (int)(totalTime/1000),
(int)(totalTime%1000));
}
if( showTimer ){
sqlite3_int64 elapseTime = realTime() - startTime;
fprintf(pTimer, "%3d.%03d wordcount", (int)(elapseTime/1000),
(int)(elapseTime%1000));
for(i=1; i<argc; i++) if( i!=showTimer ) fprintf(pTimer, " %s", argv[i]);
fprintf(pTimer, "\n");
}
if( showSummary ){
sqlite3_create_function(db, "checksum", -1, SQLITE_UTF8, 0,
0, checksumStep, checksumFinalize);
sqlite3_exec(db,
"SELECT 'count(*): ', count(*) FROM wordcount;\n"
"SELECT 'sum(cnt): ', sum(cnt) FROM wordcount;\n"
"SELECT 'max(cnt): ', max(cnt) FROM wordcount;\n"
"SELECT 'avg(cnt): ', avg(cnt) FROM wordcount;\n"
"SELECT 'sum(cnt=1):', sum(cnt=1) FROM wordcount;\n"
"SELECT 'top 10: ', group_concat(word, ', ') FROM "
"(SELECT word FROM wordcount ORDER BY cnt DESC, word LIMIT 10);\n"
"SELECT 'checksum: ', checksum(word, cnt) FROM "
"(SELECT word, cnt FROM wordcount ORDER BY word);\n"
"PRAGMA integrity_check;\n",
printResult, 0, 0);
}
/* Database connection statistics printed after both prepared statements
** have been finalized */
if( showStats ){
+72
View File
@@ -226,6 +226,56 @@ static void traceNoop(void *NotUsed, const char *zMsg){
}
#endif
/***************************************************************************
** String accumulator object
*/
typedef struct Str Str;
struct Str {
char *z; /* The string. Memory from malloc() */
sqlite3_uint64 n; /* Bytes of input used */
sqlite3_uint64 nAlloc; /* Bytes allocated to z[] */
int oomErr; /* OOM error has been seen */
};
/* Initialize a Str object */
static void StrInit(Str *p){
memset(p, 0, sizeof(*p));
}
/* Append text to the end of a Str object */
static void StrAppend(Str *p, const char *z){
sqlite3_uint64 n = strlen(z);
if( p->n + n >= p->nAlloc ){
char *zNew;
sqlite3_uint64 nNew;
if( p->oomErr ) return;
nNew = p->nAlloc*2 + 100 + n;
zNew = sqlite3_realloc(p->z, nNew);
if( zNew==0 ){
sqlite3_free(p->z);
memset(p, 0, sizeof(*p));
p->oomErr = 1;
return;
}
p->z = zNew;
p->nAlloc = nNew;
}
memcpy(p->z + p->n, z, n);
p->n += n;
p->z[p->n] = 0;
}
/* Return the current string content */
static char *StrStr(Str *p){
return p->z;
}
/* Free the string */
static void StrFree(Str *p){
sqlite3_free(p->z);
StrInit(p);
}
/***************************************************************************
** eval() implementation copied from ../ext/misc/eval.c
*/
@@ -1028,6 +1078,8 @@ int main(int argc, char **argv){
oomCnt = 0;
}
do{
Str sql;
StrInit(&sql);
if( zDbName ){
rc = sqlite3_open_v2(zDbName, &db, SQLITE_OPEN_READWRITE, 0);
if( rc!=SQLITE_OK ){
@@ -1057,6 +1109,25 @@ int main(int argc, char **argv){
if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
iStart = timeOfDay();
/* If using an input database file and that database contains a table
** named "autoexec" with a column "sql", then replace the input SQL
** with the concatenated text of the autoexec table. In this way,
** if the database file is the input being fuzzed, the SQL text is
** fuzzed at the same time. */
if( sqlite3_table_column_metadata(db,0,"autoexec","sql",0,0,0,0,0)==0 ){
sqlite3_stmt *pStmt;
rc = sqlite3_prepare_v2(db, "SELECT sql FROM autoexec", -1, &pStmt, 0);
if( rc==SQLITE_OK ){
while( sqlite3_step(pStmt)==SQLITE_ROW ){
StrAppend(&sql, (const char*)sqlite3_column_text(pStmt, 0));
StrAppend(&sql, "\n");
}
}
sqlite3_finalize(pStmt);
zSql = StrStr(&sql);
}
g.bOomEnable = 1;
if( verboseFlag ){
zErrMsg = 0;
@@ -1070,6 +1141,7 @@ int main(int argc, char **argv){
}
g.bOomEnable = 0;
iEnd = timeOfDay();
StrFree(&sql);
rc = sqlite3_close(db);
if( rc ){
abendError("sqlite3_close() failed with rc=%d", rc);
-1
View File
@@ -4159,7 +4159,6 @@ void ReportTable(
*/
for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE;
for(i=0; i<lemp->nxstate; i++){
struct action *ap;
for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){
ap->x.rp->doesReduce = i;