Compare commits

...

61 Commits

Author SHA1 Message Date
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
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 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 3fd9f33bd1 Fix minor issues with the ".lint" command implemention in the shell and
the shell help text related to ".lint".

FossilOrigin-Name: 1268dc77712d85de0b62332c88b22f7489f4e87f
2016-12-16 18:41:11 +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 3c7ebeb548 Change ".fkey_missing_indexes" to ".lint fkey-indexes".
FossilOrigin-Name: ee621ade38c11806e1df57c459da5f018a6d0670
2016-12-16 17:28:56 +00:00
dan dd9e0be46a Update .fkey_missing_indexes to use the built-in pragma vtabs.
FossilOrigin-Name: 3ab05987b0cc12af64bf32d885d04aff45d7a77c
2016-12-16 16:44:27 +00:00
dan c17f6255a4 Merge the pragma-as-vtab change into this branch.
FossilOrigin-Name: 4ba45e722371ca4343e3563e7e1c2896b48c9a87
2016-12-16 16:13:45 +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
drh d8b7200b84 Fix an error in the way the "schema" argument to some pragma virtual tables
is handled.

FossilOrigin-Name: 546821e29edb0282a4b1d8f49512e36027a6bf6d
2016-12-16 04:20:27 +00:00
drh 30776acd74 Simplifications to facilitate full test coverage.
FossilOrigin-Name: 01afc515970a868c6a36d9a598453d0fde9e39ca
2016-12-16 02:31:50 +00:00
drh 9a63f09204 Minor bug fixes and enhancements to the pragma eponymous virtual tables.
FossilOrigin-Name: 3f8f461504139a4efea0e033e3a274cc4b2d3072
2016-12-16 02:14:15 +00:00
drh c06bbceb9c Merge enhancements from trunk, and especially the ability to use
temp.sqlite_master as an alias for sqlite_temp_master.

FossilOrigin-Name: 994a4401f5c34fed17af420761291b03072a5ea1
2016-12-16 01:09:22 +00:00
drh e0a04a36a6 All temp.sqlite_master to be used as an alias for sqlite_temp_master.
FossilOrigin-Name: 8d646905b830d5bb29092e103ac5cb499b3c7e5a
2016-12-16 01:00:21 +00:00
drh ae7045cd53 Fix the cost estimation in the BestIndex method of the eponymous pragma
virtual table implementation.

FossilOrigin-Name: 7126807a186746a8663fbaa267d63214d06476e4
2016-12-15 21:33:55 +00:00
drh d7175ebeaf The pragma as eponymous virtual table mechanism now appears to work.
FossilOrigin-Name: 2c274a1a7b57ef1208901fbc1d96d39c0d492652
2016-12-15 21:11:15 +00:00
drh 2fcc1590c4 Code to automatically create eponymous virtual tables for read-only pragmas.
Compiles, but does not yet work.

FossilOrigin-Name: 988a61e8b03f302c69d11898d1ea95f002cba1a5
2016-12-15 20:59:03 +00:00
drh 35a1895990 Do exponential rather than linear expansion of the SrcList.a array when
appending new elements, to reduce the number of malloc() calls.

FossilOrigin-Name: 4e3749127e7249f46e17bfabc614b0876f60565a
2016-12-15 18:59:14 +00:00
dan f9647b6625 Add the -groupbyparent option to the ".fkey_missing_indexes" command.
FossilOrigin-Name: 976c51b4836dfba2ce9b246334a85bda08ac526f
2016-12-15 06:01:40 +00:00
dan 35ac58eabc Add the experimental ".fkey_missing_indexes" command to the shell tool. To
identify indexes that should be created on child keys if FK processing is to
be enabled.

FossilOrigin-Name: 7df23aca1f7c7b769d614d740b3fda3073f46ba9
2016-12-14 19:28:27 +00:00
74 changed files with 2928 additions and 464 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)"
+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 \
+80 -75
View File
@@ -1,6 +1,6 @@
C Do\smore\spragma\sprocessing\sfrom\stables\srather\sthan\sin-line\scode.
D 2016-12-15T16:01:17.867
F Makefile.in c194b58fe00c370a48ac6ae6945e92a7781db1c8
C Version\s3.16.0
D 2017-01-02T11:57:58.484
F Makefile.in 41bd4cad981487345c4a84081074bcdb876e4b2e
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
@@ -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
@@ -324,28 +324,28 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 0f83ee1d5963e85f8f3316cb11a90227807a74c8
F src/analyze.c 8b62b2cf4da85451534ac0af82cafc418d837f68
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
F src/analyze.c 3c4a63ff7a55faefecf6eb1589932fdbc06b2415
F src/attach.c f6725410c184a80d8141b294fdf98a854c8a52b5
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/btree.c d2c100618784bd89c089fcef03ff6e789768ecae
F src/btree.h 2349a588abcd7e0c04f984e15c5c777b61637583
F src/btreeInt.h 10c4b77c2fb399580babbcc7cf652ac10dba796e
F src/build.c e2b32766847eb16d4314c99067571ae08b888dfe
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 3b662f58b50ba12c004b2d9bd8d3ff5fddbbae7f
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
F src/func.c 43916c1d8e6da5d107d91d2b212577d4f69a876a
F src/global.c 235021a21ee2cb52b304589f8f9e85a36bbe24fa
F src/func.c d8582ee91975975645f206db332c38f534b783ad
F src/global.c dcdb89f30b7aa531c5660030af106bc5bc48ef2e
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 78f85cf6c668b084702bb305bd4980b4813afa70
F src/pragma.h 7dff1007ade3aabf8b2e467107b4506940c0ad86
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 f1c7fde7a83421e6ed620df41d200674a2327e65
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 657a892d885253768c82f1e04e8053468b13cb6a
F src/sqliteInt.h 2075e22d50833ca2d9956d0b7a6bfb845ad05dd2
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
@@ -448,23 +448,23 @@ 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 3419bb9862983d84d70735fb4c94b21b934cd0c5
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 2d90c42f2117b36e92c3af6a9c9f380b22e6e3b8
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 2d5db3fd68c41c5a7476e43e79eb54181fa01713
F src/vtab.c c4bbe0f870f52036553f8098aee0703997f0577a
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
@@ -479,10 +479,10 @@ F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
F test/alter.test 2facdddf08d0d48e75dc6cc312cd2b030f4835dd
F test/alter.test b820ab9dcf85f8e3a65bc8326accb2f0c7be64ef
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3
F test/alter4.test 0c33c542247ba5aee4f4a0133ac44bcf8f97e5e0
F test/alter4.test b6d7b86860111864f6cddb54af313f5862dda23b
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 3eb35a4af972f98422e5dc0586501b17d103d321
@@ -506,15 +506,15 @@ F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd
F test/attach.test 437107943f14d131cf5efc2ae5305a94d7cb1d58
F test/attach.test 9976867b1a6585018f0966857aa82ed44e0bd6dc
F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
F test/auth.test 872a122b3977c1d1bb9fd637dc20016e5c01880f
F test/auth.test c6ede04bee65637ff354b43fc1235aa560c0863e
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test b810826b193831929951c0d50783a200e5ef6b72
F test/autoinc.test c3a55c3667f429f4f4c7bed05f67b4d93e89e79d
F test/auth3.test 0d48b901cf111c14b4b1b5205c7d28f1a278190f
F test/autoinc.test 6ae8fb69c9f656962464ae4e6667045d0dfc3b46
F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
@@ -535,8 +535,8 @@ F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
F test/bestindex1.test 0cf1bd2d7b97d3a3a8c10736125274f64765c4ee
F test/bestindex2.test 4a06b8922ab2fd09434870da8d1cdf525aaf7060
F test/bestindex3.test dd5fa4f483cd0356549203c4522f8c9e21cb1fc0
F test/bestindex4.test e6ef2ffe5787e6dbacb5f934ee3f32cf106474a1
F test/bestindex3.test 578b6a52dab819e63f28e3640e04b32c85aed320
F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
@@ -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
@@ -650,7 +651,7 @@ F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
F test/e_expr.test d0dd488e0527cbc560ae2dea1939cc44cb9b9924
F test/e_fkey.test 54cc0046d2d952d6c42b0dd94414e7a8f75f79f4
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
@@ -685,7 +686,7 @@ F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
F test/filefmt.test e4edbdc637ca9576ccf4337a3cce627d9df7a56c
F test/fkey1.test ba64806ff9a04eecab2679caad377ae99a5e94e4
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
F test/fkey2.test 155809016fad6b2a1491facf2ac53a551bc57c2c
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 5a373303f201ac03c22ba1ef17a733d3f56e611a
@@ -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
@@ -839,7 +841,7 @@ F test/in5.test 6c006e0bcd7351b69350ef566e65f244023489e9
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
F test/incrblob4.test fab83541571c7281aa561e5ea6088eb8612a4bec
F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
@@ -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/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc
F test/interrupt2.test 829b06f9e20a6c378d8bd121b26c337f4dfa36e5
F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba
F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a
F test/intarray.test 46d95b457916638c5d8b1af21fb174804b3acf8b
F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054
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
@@ -1022,7 +1025,7 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test aa7ffcc21350007a78361b82bcf3b74d12227144
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl cb06c4df0de4872e65b178316f8a87ccf7624d59 x
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
@@ -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 3f468a9e370a3ee8b267e58049679eb0df2b9d01
F test/rowvalue.test 1701fb786188e9fb7934a7c155bd9cc587d9b677
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
F test/rowvalue4.test 4b556d7de161a0dd8cff095c336e913986398bea
@@ -1040,8 +1043,8 @@ F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6
F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
F test/rowvalue9.test e24f9eb02baffc6a67b6eed9e40d4c612c98079d
F test/rowvaluefault.test 7b16485e3f2b371f3e3d05455b8ded6d0c090244
F test/rowvalue9.test d8dd2c6ecac432dadaa79e41dc2434f007be1b6b
F test/rowvaluefault.test 7cd9ccc6c2fbdd881672984087aad0491bb75504
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
F test/savepoint.test c671fdbd34cd3bfe1518a777526ada595180cf8d
@@ -1055,7 +1058,7 @@ F test/scanstatus.test 5253c219e331318a437f436268e0e82345700285
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5
F test/schema4.test 3b26c9fa916abb6dadf894137adcf41b7796f7b9
F test/schema5.test 29699b4421f183c8f0e88bd28ce7d75d13ea653e
F test/securedel.test 21749c32ccc30f1ea9e4b9f33295a6521ec20fa0
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
@@ -1089,11 +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 cff624fadf71bdb5e3a9b0f86eaf59a43c0622b1
F test/shell7.test 07751911b294698e0c5df67bcbd29e7d2f0f2907
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
@@ -1104,7 +1109,7 @@ F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
F test/snapshot.test 85735bd997a4f6d710140c28fd860519a299649f
F test/snapshot2.test eb083df2e617708a4a93d70965f14268d4934120
F test/snapshot2.test 867652ed4a13282dce218723535fad1c7b44c3c4
F test/snapshot_fault.test 52c5e97ebd218846a8ae2da4d147d3e77d71f963
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
@@ -1148,12 +1153,12 @@ F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test 1d73b9203b1ca8798d7d7310742b8d3febc0d56e
F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
F test/tempdb2.test 4fc92055f2a3f7626c0f2eabbb637dc021b311d5
F test/tempdb2.test 27e41ed540b2f9b056c2e77e9bddc1b875358507
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 4ce5afd5e192db4cae178e1a983b060e0f08c5d6
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
@@ -1284,7 +1289,7 @@ F test/tkt3541.test 5dc257bde9bc833ab9cc6844bf170b998dbb950a
F test/tkt3554.test f599967f279077bace39220cbe76085c7b423725
F test/tkt3581.test 1966b7193f1e3f14951cce8c66907ae69454e9a3
F test/tkt35xx.test f38c1b03713179d414969187c941466e44945b35
F test/tkt3630.test 929f64852103054125200bc825c316d5f75d42f7
F test/tkt3630.test 9a934c58c259f89a0ae6bb6bb846c56285a6fd0f
F test/tkt3718.test 3b59dcb5c4e7754dacd91e7fd353a61492cc402a
F test/tkt3731.test 0c5f4cbffe102d43c3b2188af91a9e36348f974b
F test/tkt3757.test 10cd679a88675c880533083fc79ac04324525595
@@ -1293,7 +1298,7 @@ F test/tkt3762.test 4d439ff7abdc8d9323150269d182c37c2d514576
F test/tkt3773.test 7bca904d2a647a6a4a291bd86d7fd7c73855b789
F test/tkt3791.test a6624b9a80b216a26cf473607f42f3e51898c267
F test/tkt3793.test d90ffd75c52413908d15e1c44fc2ea9c80fcc449
F test/tkt3810.test 90fa0635dfa7da9680c8cd3513350a49b3a8ae12
F test/tkt3810.test 09608d81c63a6ff3aaf7bc70717909c51f5f4048
F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0
F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d
F test/tkt3838.test 292e72489101cd1320d7278dc111c173ebf334d4
@@ -1436,11 +1441,11 @@ 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
F test/without_rowid3.test aad4f9d383e199349b6c7e508a778f7dff5dff79
F test/without_rowid3.test 2724c787a51a5dce09d078453a758117b4b728f1
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
@@ -1459,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
@@ -1474,7 +1479,7 @@ F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61cf81820a2da96c79ed1ca8d
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 999d7da2b77e83f24de01c3c8f90dc66411ce6d2
F tool/mkpragmatab.tcl a30ee93515135466fc49ae881f75da07ebcafd19
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
@@ -1536,10 +1541,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 9cae4c2e300e20304ced0dc8c1415c4922185928
R d8e6c9c98262f0aea48f528b484866a4
T *branch * table-driven-pragma
T *sym-table-driven-pragma *
T -sym-trunk *
P 2c4d167ccd4be591487f404de9ee629fd484c8bf
R b92eb609c667e98735c96cb1ee09a168
T +bgcolor * #d0c0ff
T +sym-release *
T +sym-version-3.16.0 *
U drh
Z 7260d2e6fdce7485555b88e6d856ce9f
Z d8ea167822373183dd9b5b971ee1941f
+1 -1
View File
@@ -1 +1 @@
a88ca3524b97f296dffc68335466b3767a681747
04ac0b75b1716541b2b97704f4809cb7ef19cccf
+3 -3
View File
@@ -504,7 +504,7 @@ void sqlite3AlterRenameTable(
sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"sql = sqlite_rename_parent(sql, %Q, %Q) "
"WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
"WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere);
sqlite3DbFree(db, zWhere);
}
}
@@ -528,7 +528,7 @@ void sqlite3AlterRenameTable(
"ELSE name END "
"WHERE tbl_name=%Q COLLATE nocase AND "
"(type='table' OR type='index' OR type='trigger');",
zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
zDb, MASTER_NAME, zName, zName, zName,
#ifndef SQLITE_OMIT_TRIGGER
zName,
#endif
@@ -689,7 +689,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
"UPDATE \"%w\".%s SET "
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
"WHERE type = 'table' AND name = %Q",
zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
sqlite3DbFree(db, zCol);
+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);
+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]);
+34 -21
View File
@@ -30,10 +30,10 @@
** codeTableLocks() functions.
*/
struct TableLock {
int iDb; /* The database containing the table to be locked */
int iTab; /* The root page of the table to be locked */
u8 isWriteLock; /* True for write lock. False for a read lock */
const char *zName; /* Name of the table */
int iDb; /* The database containing the table to be locked */
int iTab; /* The root page of the table to be locked */
u8 isWriteLock; /* True for write lock. False for a read lock */
const char *zLockName; /* Name of the table */
};
/*
@@ -77,7 +77,7 @@ void sqlite3TableLock(
p->iDb = iDb;
p->iTab = iTab;
p->isWriteLock = isWriteLock;
p->zName = zName;
p->zLockName = zName;
}else{
pToplevel->nTableLock = 0;
sqlite3OomFault(pToplevel->db);
@@ -99,7 +99,7 @@ static void codeTableLocks(Parse *pParse){
TableLock *p = &pParse->aTableLock[i];
int p1 = p->iDb;
sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
p->zName, P4_STATIC);
p->zLockName, P4_STATIC);
}
}
#else
@@ -308,15 +308,22 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
return 0;
}
#endif
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
assert( sqlite3SchemaMutexHeld(db, j, 0) );
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
if( p ) break;
while(1){
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
assert( sqlite3SchemaMutexHeld(db, j, 0) );
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
if( p ) return p;
}
}
/* Not found. If the name we were looking for was temp.sqlite_master
** then change the name to sqlite_temp_master and try again. */
if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
zName = TEMP_MASTER_NAME;
}
return p;
return 0;
}
/*
@@ -352,6 +359,9 @@ Table *sqlite3LocateTable(
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName);
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(pParse->db, zName);
}
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
return pMod->pEpoTab;
}
@@ -688,7 +698,7 @@ char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
*/
void sqlite3OpenMasterTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME);
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
@@ -706,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;
@@ -1991,7 +2004,7 @@ void sqlite3EndTable(
"UPDATE %Q.%s "
"SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
"WHERE rowid=#%d",
db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
db->aDb[iDb].zDbSName, MASTER_NAME,
zType,
p->zName,
p->zName,
@@ -2328,7 +2341,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
*/
sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
pParse->db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), iTable, r1, r1);
pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1);
#endif
sqlite3ReleaseTempReg(pParse, r1);
}
@@ -2471,7 +2484,7 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
*/
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
pDb->zDbSName, SCHEMA_TABLE(iDb), pTab->zName);
pDb->zDbSName, MASTER_NAME, pTab->zName);
if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
@@ -3363,7 +3376,7 @@ void sqlite3CreateIndex(
*/
sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
db->aDb[iDb].zDbSName, MASTER_NAME,
pIndex->zName,
pTab->zName,
iMem,
@@ -3515,7 +3528,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName
db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName
);
sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
sqlite3ChangeCookie(pParse, iDb);
@@ -3658,7 +3671,7 @@ SrcList *sqlite3SrcListEnlarge(
/* Allocate additional space if needed */
if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
SrcList *pNew;
int nAlloc = pSrc->nSrc+nExtra;
int nAlloc = pSrc->nSrc*2+nExtra;
int nGot;
pNew = sqlite3DbRealloc(db, pSrc,
sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
+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;
}
/*
+26 -32
View File
@@ -527,7 +527,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 +937,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 +948,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 +959,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 +977,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");
}
}
@@ -3430,9 +3423,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;
}
+22 -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]);
+2 -2
View File
@@ -181,8 +181,8 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
128, /* szLookaside */
500, /* nLookaside */
512, /* szLookaside */
125, /* 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;
}
+331 -18
View File
@@ -166,8 +166,8 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
** Set result column names for a pragma.
*/
static void setPragmaResultColumnNames(
Vdbe *v, /* The query under construction */
const struct sPragmaNames *pPragma /* The pragma */
Vdbe *v, /* The query under construction */
const PragmaName *pPragma /* The pragma */
){
u8 n = pPragma->nPragCName;
sqlite3VdbeSetNumCols(v, n==0 ? 1 : n);
@@ -275,6 +275,26 @@ const char *sqlite3JournalModename(int eMode){
return azModeName[eMode];
}
/*
** Locate a pragma in the aPragmaName[] array.
*/
static const PragmaName *pragmaLocate(const char *zName){
int upr, lwr, mid, rc;
lwr = 0;
upr = ArraySize(aPragmaName)-1;
while( lwr<=upr ){
mid = (lwr+upr)/2;
rc = sqlite3_stricmp(zName, aPragmaName[mid].zName);
if( rc==0 ) break;
if( rc<0 ){
upr = mid - 1;
}else{
lwr = mid + 1;
}
}
return lwr>upr ? 0 : &aPragmaName[mid];
}
/*
** Process a pragma statement.
**
@@ -303,12 +323,11 @@ void sqlite3Pragma(
Token *pId; /* Pointer to <id> token */
char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
int iDb; /* Database index for <database> */
int lwr, upr, mid = 0; /* Binary search bounds */
int rc; /* return value form SQLITE_FCNTL_PRAGMA */
sqlite3 *db = pParse->db; /* The database connection */
Db *pDb; /* The specific database being pragmaed */
Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */
const struct sPragmaNames *pPragma;
const PragmaName *pPragma; /* The pragma */
if( v==0 ) return;
sqlite3VdbeRunOnlyOnce(v);
@@ -380,20 +399,8 @@ void sqlite3Pragma(
}
/* Locate the pragma in the lookup table */
lwr = 0;
upr = ArraySize(aPragmaNames)-1;
while( lwr<=upr ){
mid = (lwr+upr)/2;
rc = sqlite3_stricmp(zLeft, aPragmaNames[mid].zName);
if( rc==0 ) break;
if( rc<0 ){
upr = mid - 1;
}else{
lwr = mid + 1;
}
}
if( lwr>upr ) goto pragma_out;
pPragma = &aPragmaNames[mid];
pPragma = pragmaLocate(zLeft);
if( pPragma==0 ) goto pragma_out;
/* Make sure the database schema is loaded if the pragma requires that */
if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
@@ -1950,5 +1957,311 @@ pragma_out:
sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*****************************************************************************
** Implementation of an eponymous virtual table that runs a pragma.
**
*/
typedef struct PragmaVtab PragmaVtab;
typedef struct PragmaVtabCursor PragmaVtabCursor;
struct PragmaVtab {
sqlite3_vtab base; /* Base class. Must be first */
sqlite3 *db; /* The database connection to which it belongs */
const PragmaName *pName; /* Name of the pragma */
u8 nHidden; /* Number of hidden columns */
u8 iHidden; /* Index of the first hidden column */
};
struct PragmaVtabCursor {
sqlite3_vtab_cursor base; /* Base class. Must be first */
sqlite3_stmt *pPragma; /* The pragma statement to run */
sqlite_int64 iRowid; /* Current rowid */
char *azArg[2]; /* Value of the argument and schema */
};
/*
** Pragma virtual table module xConnect method.
*/
static int pragmaVtabConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
const PragmaName *pPragma = (const PragmaName*)pAux;
PragmaVtab *pTab = 0;
int rc;
int i, j;
char cSep = '(';
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++){
sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]);
cSep = ',';
}
if( i==0 ){
sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName);
cSep = ',';
i++;
}
j = 0;
if( pPragma->mPragFlg & PragFlg_Result1 ){
sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN");
j++;
}
if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){
sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN");
j++;
}
sqlite3StrAccumAppend(&acc, ")", 1);
sqlite3StrAccumFinish(&acc);
assert( strlen(zBuf) < sizeof(zBuf)-1 );
rc = sqlite3_declare_vtab(db, zBuf);
if( rc==SQLITE_OK ){
pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab));
if( pTab==0 ){
rc = SQLITE_NOMEM;
}else{
memset(pTab, 0, sizeof(PragmaVtab));
pTab->pName = pPragma;
pTab->db = db;
pTab->iHidden = i;
pTab->nHidden = j;
}
}else{
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
*ppVtab = (sqlite3_vtab*)pTab;
return rc;
}
/*
** Pragma virtual table module xDisconnect method.
*/
static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){
PragmaVtab *pTab = (PragmaVtab*)pVtab;
sqlite3_free(pTab);
return SQLITE_OK;
}
/* Figure out the best index to use to search a pragma virtual table.
**
** There are not really any index choices. But we want to encourage the
** query planner to give == constraints on as many hidden parameters as
** possible, and especially on the first hidden parameter. So return a
** high cost if hidden parameters are unconstrained.
*/
static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
PragmaVtab *pTab = (PragmaVtab*)tab;
const struct sqlite3_index_constraint *pConstraint;
int i, j;
int seen[2];
pIdxInfo->estimatedCost = (double)1;
if( pTab->nHidden==0 ){ return SQLITE_OK; }
pConstraint = pIdxInfo->aConstraint;
seen[0] = 0;
seen[1] = 0;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->usable==0 ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pConstraint->iColumn < pTab->iHidden ) continue;
j = pConstraint->iColumn - pTab->iHidden;
assert( j < 2 );
seen[j] = i+1;
}
if( seen[0]==0 ){
pIdxInfo->estimatedCost = (double)2147483647;
pIdxInfo->estimatedRows = 2147483647;
return SQLITE_OK;
}
j = seen[0]-1;
pIdxInfo->aConstraintUsage[j].argvIndex = 1;
pIdxInfo->aConstraintUsage[j].omit = 1;
if( seen[1]==0 ) return SQLITE_OK;
pIdxInfo->estimatedCost = (double)20;
pIdxInfo->estimatedRows = 20;
j = seen[1]-1;
pIdxInfo->aConstraintUsage[j].argvIndex = 2;
pIdxInfo->aConstraintUsage[j].omit = 1;
return SQLITE_OK;
}
/* Create a new cursor for the pragma virtual table */
static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
PragmaVtabCursor *pCsr;
pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr));
if( pCsr==0 ) return SQLITE_NOMEM;
memset(pCsr, 0, sizeof(PragmaVtabCursor));
pCsr->base.pVtab = pVtab;
*ppCursor = &pCsr->base;
return SQLITE_OK;
}
/* Clear all content from pragma virtual table cursor. */
static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
int i;
sqlite3_finalize(pCsr->pPragma);
pCsr->pPragma = 0;
for(i=0; i<ArraySize(pCsr->azArg); i++){
sqlite3_free(pCsr->azArg[i]);
pCsr->azArg[i] = 0;
}
}
/* Close a pragma virtual table cursor */
static int pragmaVtabClose(sqlite3_vtab_cursor *cur){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur;
pragmaVtabCursorClear(pCsr);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/* Advance the pragma virtual table cursor to the next row */
static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
int rc = SQLITE_OK;
/* Increment the xRowid value */
pCsr->iRowid++;
assert( pCsr->pPragma );
if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){
rc = sqlite3_finalize(pCsr->pPragma);
pCsr->pPragma = 0;
pragmaVtabCursorClear(pCsr);
}
return rc;
}
/*
** Pragma virtual table module xFilter method.
*/
static int pragmaVtabFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
int rc;
int i, j;
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++){
assert( j<ArraySize(pCsr->azArg) );
pCsr->azArg[j] = sqlite3_mprintf("%s", sqlite3_value_text(argv[i]));
if( pCsr->azArg[j]==0 ){
return SQLITE_NOMEM;
}
}
sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]);
sqlite3StrAccumAppendAll(&acc, "PRAGMA ");
if( pCsr->azArg[1] ){
sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]);
}
sqlite3StrAccumAppendAll(&acc, pTab->pName->zName);
if( pCsr->azArg[0] ){
sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]);
}
zSql = sqlite3StrAccumFinish(&acc);
if( zSql==0 ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK ){
pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
return rc;
}
return pragmaVtabNext(pVtabCursor);
}
/*
** Pragma virtual table module xEof method.
*/
static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
return (pCsr->pPragma==0);
}
/* The xColumn method simply returns the corresponding column from
** the PRAGMA.
*/
static int pragmaVtabColumn(
sqlite3_vtab_cursor *pVtabCursor,
sqlite3_context *ctx,
int i
){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
if( i<pTab->iHidden ){
sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i));
}else{
sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT);
}
return SQLITE_OK;
}
/*
** Pragma virtual table module xRowid method.
*/
static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
*p = pCsr->iRowid;
return SQLITE_OK;
}
/* The pragma virtual table object */
static const sqlite3_module pragmaVtabModule = {
0, /* iVersion */
0, /* xCreate - create a table */
pragmaVtabConnect, /* xConnect - connect to an existing table */
pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */
pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */
0, /* xDestroy - Drop a table */
pragmaVtabOpen, /* xOpen - open a cursor */
pragmaVtabClose, /* xClose - close a cursor */
pragmaVtabFilter, /* xFilter - configure scan constraints */
pragmaVtabNext, /* xNext - advance a cursor */
pragmaVtabEof, /* xEof */
pragmaVtabColumn, /* xColumn - read data */
pragmaVtabRowid, /* xRowid - read data */
0, /* xUpdate - write data */
0, /* xBegin - begin transaction */
0, /* xSync - sync transaction */
0, /* xCommit - commit transaction */
0, /* xRollback - rollback transaction */
0, /* xFindFunction - function overloading */
0, /* xRename - rename the table */
0, /* xSavepoint */
0, /* xRelease */
0 /* xRollbackTo */
};
/*
** Check to see if zTabName is really the name of a pragma. If it is,
** then register an eponymous virtual table for that pragma and return
** a pointer to the Module object for the new virtual table.
*/
Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){
const PragmaName *pName;
assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 );
pName = pragmaLocate(zName+7);
if( pName==0 ) return 0;
if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0;
assert( sqlite3HashFind(&db->aModule, zName)==0 );
return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, (void*)pName, 0);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#endif /* SQLITE_OMIT_PRAGMA */
+3 -2
View File
@@ -114,14 +114,15 @@ static const char *const pragCName[] = {
};
/* Definitions of all built-in pragmas */
static const struct sPragmaNames {
typedef struct PragmaName {
const char *const zName; /* Name of pragma */
u8 ePragTyp; /* PragTyp_XXX value */
u8 mPragFlg; /* Zero or more PragFlg_XXX values */
u8 iPragCName; /* Start of column names in pragCName[] */
u8 nPragCName; /* Num of col names. 0 means use pragma name */
u32 iArg; /* Extra argument */
} aPragmaNames[] = {
} PragmaName;
static const PragmaName aPragmaName[] = {
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
{/* zName: */ "activate_extensions",
/* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
+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);
+309 -76
View File
@@ -2199,6 +2199,8 @@ static char zHelp[] =
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
#endif
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
".lint OPTIONS Report potential schema issues. Options:\n"
" fkey-indexes Find missing foreign key indexes\n"
#ifndef SQLITE_OMIT_LOAD_EXTENSION
".load FILE ?ENTRY? Load an extension library\n"
#endif
@@ -2278,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;
@@ -2303,6 +2313,7 @@ static char *readFile(const char *zName){
return 0;
}
pBuf[nIn] = 0;
if( pnByte ) *pnByte = nIn;
return pBuf;
}
@@ -2318,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);
}
/*
@@ -3253,6 +3265,253 @@ int shellDeleteFile(const char *zFilename){
return rc;
}
/*
** The implementation of SQL scalar function fkey_collate_clause(), used
** by the ".lint fkey-indexes" command. This scalar function is always
** called with four arguments - the parent table name, the parent column name,
** the child table name and the child column name.
**
** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
**
** If either of the named tables or columns do not exist, this function
** returns an empty string. An empty string is also returned if both tables
** and columns exist but have the same default collation sequence. Or,
** if both exist but the default collation sequences are different, this
** function returns the string " COLLATE <parent-collation>", where
** <parent-collation> is the default collation sequence of the parent column.
*/
static void shellFkeyCollateClause(
sqlite3_context *pCtx,
int nVal,
sqlite3_value **apVal
){
sqlite3 *db = sqlite3_context_db_handle(pCtx);
const char *zParent;
const char *zParentCol;
const char *zParentSeq;
const char *zChild;
const char *zChildCol;
const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
int rc;
assert( nVal==4 );
zParent = (const char*)sqlite3_value_text(apVal[0]);
zParentCol = (const char*)sqlite3_value_text(apVal[1]);
zChild = (const char*)sqlite3_value_text(apVal[2]);
zChildCol = (const char*)sqlite3_value_text(apVal[3]);
sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
rc = sqlite3_table_column_metadata(
db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
);
if( rc==SQLITE_OK ){
rc = sqlite3_table_column_metadata(
db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
);
}
if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
sqlite3_free(z);
}
}
/*
** The implementation of dot-command ".lint fkey-indexes".
*/
static int lintFkeyIndexes(
ShellState *pState, /* Current shell tool state */
char **azArg, /* Array of arguments passed to dot command */
int nArg /* Number of entries in azArg[] */
){
sqlite3 *db = pState->db; /* Database handle to query "main" db of */
FILE *out = pState->out; /* Stream to write non-error output to */
int bVerbose = 0; /* If -verbose is present */
int bGroupByParent = 0; /* If -groupbyparent is present */
int i; /* To iterate through azArg[] */
const char *zIndent = ""; /* How much to indent CREATE INDEX by */
int rc; /* Return code */
sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
/*
** This SELECT statement returns one row for each foreign key constraint
** in the schema of the main database. The column values are:
**
** 0. The text of an SQL statement similar to:
**
** "EXPLAIN QUERY PLAN SELECT rowid FROM child_table WHERE child_key=?"
**
** This is the same SELECT that the foreign keys implementation needs
** to run internally on child tables. If there is an index that can
** be used to optimize this query, then it can also be used by the FK
** implementation to optimize DELETE or UPDATE statements on the parent
** table.
**
** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
** contains an index that can be used to optimize the query.
**
** 2. Human readable text that describes the child table and columns. e.g.
**
** "child_table(child_key1, child_key2)"
**
** 3. Human readable text that describes the parent table and columns. e.g.
**
** "parent_table(parent_key1, parent_key2)"
**
** 4. A full CREATE INDEX statement for an index that could be used to
** optimize DELETE or UPDATE statements on the parent table. e.g.
**
** "CREATE INDEX child_table_child_key ON child_table(child_key)"
**
** 5. The name of the parent table.
**
** These six values are used by the C logic below to generate the report.
*/
const char *zSql =
"SELECT "
" 'EXPLAIN QUERY PLAN SELECT rowid FROM ' || quote(s.name) || ' WHERE '"
" || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
" || fkey_collate_clause(f.[table], f.[to], s.name, f.[from]),' AND ')"
", "
" 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
" || group_concat('*=?', ' AND ') || ')'"
", "
" s.name || '(' || group_concat(f.[from], ', ') || ')'"
", "
" f.[table] || '(' || group_concat(COALESCE(f.[to], "
" (SELECT name FROM pragma_table_info(f.[table]) WHERE pk=seq+1)"
" )) || ')'"
", "
" 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
" || ' ON ' || quote(s.name) || '('"
" || group_concat(quote(f.[from]) ||"
" fkey_collate_clause(f.[table], f.[to], s.name, f.[from]), ', ')"
" || ');'"
", "
" f.[table] "
"FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f "
"GROUP BY s.name, f.id "
"ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
;
for(i=2; i<nArg; i++){
int n = (int)strlen(azArg[i]);
if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
bVerbose = 1;
}
else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
bGroupByParent = 1;
zIndent = " ";
}
else{
raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
azArg[0], azArg[1]
);
return SQLITE_ERROR;
}
}
/* Register the fkey_collate_clause() SQL function */
rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
0, shellFkeyCollateClause, 0, 0
);
if( rc==SQLITE_OK ){
rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
}
if( rc==SQLITE_OK ){
sqlite3_bind_int(pSql, 1, bGroupByParent);
}
if( rc==SQLITE_OK ){
int rc2;
char *zPrev = 0;
while( SQLITE_ROW==sqlite3_step(pSql) ){
int res = -1;
sqlite3_stmt *pExplain = 0;
const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
if( rc!=SQLITE_OK ) break;
if( SQLITE_ROW==sqlite3_step(pExplain) ){
const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
res = (0==sqlite3_strglob(zGlob, zPlan));
}
rc = sqlite3_finalize(pExplain);
if( rc!=SQLITE_OK ) break;
if( res<0 ){
raw_printf(stderr, "Error: internal error");
break;
}else{
if( bGroupByParent
&& (bVerbose || res==0)
&& (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
){
raw_printf(out, "-- Parent table %s\n", zParent);
sqlite3_free(zPrev);
zPrev = sqlite3_mprintf("%s", zParent);
}
if( res==0 ){
raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
}else if( bVerbose ){
raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
zIndent, zFrom, zTarget
);
}
}
}
sqlite3_free(zPrev);
if( rc!=SQLITE_OK ){
raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
}
rc2 = sqlite3_finalize(pSql);
if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
rc = rc2;
raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
}
}else{
raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
}
return rc;
}
/*
** Implementation of ".lint" dot command.
*/
static int lintDotCommand(
ShellState *pState, /* Current shell tool state */
char **azArg, /* Array of arguments passed to dot command */
int nArg /* Number of entries in azArg[] */
){
int n;
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);
usage:
raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
raw_printf(stderr, "Where sub-commands are:\n");
raw_printf(stderr, " fkey-indexes\n");
return SQLITE_ERROR;
}
/*
** If an input line begins with "." then invoke this routine to
** process that line.
@@ -3416,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 ){
@@ -3445,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);
@@ -3832,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;
@@ -4033,6 +4245,11 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
open_db(p, 0);
lintDotCommand(p, azArg, nArg);
}else
#ifndef SQLITE_OMIT_LOAD_EXTENSION
if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
const char *zFile, *zProc;
@@ -4696,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;
@@ -4709,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);
+22 -2
View File
@@ -1046,6 +1046,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
@@ -2952,7 +2960,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 +2971,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 */
@@ -3563,6 +3570,9 @@ u32 sqlite3ExprListFlags(const ExprList*);
int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**);
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
#ifndef SQLITE_OMIT_VIRTUALTABLE
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
#endif
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);
@@ -3861,6 +3871,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
@@ -4077,6 +4090,13 @@ void sqlite3AutoLoadExtensions(sqlite3*);
int sqlite3VtabSavepoint(sqlite3 *, int, int);
void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
VTable *sqlite3GetVTable(sqlite3*, Table*);
Module *sqlite3VtabCreateModule(
sqlite3*,
const char*,
const sqlite3_module*,
void*,
void(*)(void*)
);
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
int sqlite3VtabEponymousTableInit(Parse*,Module*);
+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;
+2 -2
View File
@@ -308,7 +308,7 @@ void sqlite3FinishTrigger(
z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zName,
db->aDb[iDb].zDbSName, MASTER_NAME, zName,
pTrig->table, z);
sqlite3DbFree(db, z);
sqlite3ChangeCookie(pParse, iDb);
@@ -559,7 +559,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
if( (v = sqlite3GetVdbe(pParse))!=0 ){
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTrigger->zName
db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName
);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
+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;
}
+31 -17
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;
@@ -5479,7 +5493,7 @@ case OP_ParseSchema: {
assert( iDb>=0 && iDb<db->nDb );
assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
/* Used to be a conditional */ {
zMaster = SCHEMA_TABLE(iDb);
zMaster = MASTER_NAME;
initData.db = db;
initData.iDb = pOp->p1;
initData.pzErrMsg = &p->zErrMsg;
@@ -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;
}
+37 -22
View File
@@ -28,6 +28,41 @@ struct VtabCtx {
int bDeclared; /* True after sqlite3_declare_vtab() is called */
};
/*
** Construct and install a Module object for a virtual table. When this
** routine is called, it is guaranteed that all appropriate locks are held
** and the module is not already part of the connection.
*/
Module *sqlite3VtabCreateModule(
sqlite3 *db, /* Database in which module is registered */
const char *zName, /* Name assigned to this module */
const sqlite3_module *pModule, /* The definition of the module */
void *pAux, /* Context pointer for xCreate/xConnect */
void (*xDestroy)(void *) /* Module destructor function */
){
Module *pMod;
int nName = sqlite3Strlen30(zName);
pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1);
if( pMod ){
Module *pDel;
char *zCopy = (char *)(&pMod[1]);
memcpy(zCopy, zName, nName+1);
pMod->zName = zCopy;
pMod->pModule = pModule;
pMod->pAux = pAux;
pMod->xDestroy = xDestroy;
pMod->pEpoTab = 0;
pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
assert( pDel==0 || pDel==pMod );
if( pDel ){
sqlite3OomFault(db);
sqlite3DbFree(db, pDel);
pMod = 0;
}
}
return pMod;
}
/*
** The actual function that does the work of creating a new module.
** This function implements the sqlite3_create_module() and
@@ -41,35 +76,15 @@ static int createModule(
void (*xDestroy)(void *) /* Module destructor function */
){
int rc = SQLITE_OK;
int nName;
sqlite3_mutex_enter(db->mutex);
nName = sqlite3Strlen30(zName);
if( sqlite3HashFind(&db->aModule, zName) ){
rc = SQLITE_MISUSE_BKPT;
}else{
Module *pMod;
pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1);
if( pMod ){
Module *pDel;
char *zCopy = (char *)(&pMod[1]);
memcpy(zCopy, zName, nName+1);
pMod->zName = zCopy;
pMod->pModule = pModule;
pMod->pAux = pAux;
pMod->xDestroy = xDestroy;
pMod->pEpoTab = 0;
pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
assert( pDel==0 || pDel==pMod );
if( pDel ){
sqlite3OomFault(db);
sqlite3DbFree(db, pDel);
}
}
(void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
}
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -408,7 +423,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
"UPDATE %Q.%s "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
"WHERE rowid=#%d",
db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
db->aDb[iDb].zDbSName, MASTER_NAME,
pTab->zName,
pTab->zName,
zStmt,
+3 -3
View File
@@ -77,7 +77,7 @@ do_test alter-1.2 {
ifcapable tempdb {
execsql {
INSERT INTO objlist SELECT type, name, tbl_name
FROM sqlite_temp_master WHERE NAME!='objlist';
FROM temp.sqlite_master WHERE NAME!='objlist';
}
}
@@ -153,7 +153,7 @@ ifcapable tempdb {
CREATE TEMP TABLE objlist(type, name, tbl_name);
INSERT INTO objlist SELECT type, name, tbl_name FROM sqlite_master;
INSERT INTO objlist
SELECT type, name, tbl_name FROM sqlite_temp_master
SELECT type, name, tbl_name FROM temp.sqlite_master
WHERE NAME!='objlist';
SELECT type, name, tbl_name FROM objlist
ORDER BY tbl_name, type desc, name;
@@ -524,7 +524,7 @@ do_test alter-3.3.7 {
ifcapable tempdb {
do_test alter-3.3.8 {
execsql {
SELECT * FROM sqlite_temp_master WHERE type = 'trigger';
SELECT * FROM temp.sqlite_master WHERE type = 'trigger';
}
} {}
}
+20
View File
@@ -45,18 +45,33 @@ do_test alter4-1.1 {
SELECT sql FROM sqlite_temp_master;
}
} {{CREATE TABLE abc(a, b, c)}}
do_test alter4-1.1b {
execsql {
SELECT sql FROM temp.sqlite_master;
}
} {{CREATE TABLE abc(a, b, c)}}
do_test alter4-1.2 {
execsql {ALTER TABLE abc ADD d INTEGER;}
execsql {
SELECT sql FROM sqlite_temp_master;
}
} {{CREATE TABLE abc(a, b, c, d INTEGER)}}
do_test alter4-1.2b {
execsql {
SELECT sql FROM temp.sqlite_master;
}
} {{CREATE TABLE abc(a, b, c, d INTEGER)}}
do_test alter4-1.3 {
execsql {ALTER TABLE abc ADD e}
execsql {
SELECT sql FROM sqlite_temp_master;
}
} {{CREATE TABLE abc(a, b, c, d INTEGER, e)}}
do_test alter4-1.3b {
execsql {
SELECT sql FROM temp.sqlite_master;
}
} {{CREATE TABLE abc(a, b, c, d INTEGER, e)}}
do_test alter4-1.4 {
execsql {
CREATE TABLE temp.t1(a, b);
@@ -64,6 +79,11 @@ do_test alter4-1.4 {
SELECT sql FROM sqlite_temp_master WHERE tbl_name = 't1';
}
} {{CREATE TABLE t1(a, b, c)}}
do_test alter4-1.4b {
execsql {
SELECT sql FROM temp.sqlite_master WHERE tbl_name = 't1';
}
} {{CREATE TABLE t1(a, b, c)}}
do_test alter4-1.5 {
execsql {
ALTER TABLE t1 ADD d CHECK (a>d);
+1 -1
View File
@@ -193,7 +193,7 @@ do_test attach-1.20.2 {
} ;# ifcapable schema_pragmas
integrity_check attach-1.20.3
ifcapable tempdb {
execsql {select * from sqlite_temp_master}
execsql {select * from temp.sqlite_master}
}
do_test attach-1.21 {
catchsql {
+2 -2
View File
@@ -207,7 +207,7 @@ ifcapable tempdb {
CREATE TEMP TRIGGER tst_trigger BEFORE INSERT ON aux.t4 BEGIN
SELECT 'hello world';
END;
SELECT count(*) FROM sqlite_temp_master;
SELECT count(*) FROM temp.sqlite_master;
}
} {1}
do_test attach3-9.1 {
@@ -219,7 +219,7 @@ ifcapable tempdb {
do_test attach3-9.2 {
execsql {
DROP TABLE aux.t4;
SELECT count(*) FROM sqlite_temp_master;
SELECT count(*) FROM temp.sqlite_master;
}
} {0}
}
+20 -20
View File
@@ -91,7 +91,7 @@ ifcapable tempdb {
catchsql {CREATE TEMP TABLE t1(a,b,c)}
} {1 {not authorized}}
do_test auth-1.6 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {}
do_test auth-1.7.1 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -148,7 +148,7 @@ ifcapable tempdb {
catchsql {CREATE TEMP TABLE t1(a,b,c)}
} {0 {}}
do_test auth-1.14 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {}
do_test auth-1.15 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -561,7 +561,7 @@ ifcapable tempdb {
catchsql {DROP TABLE t1}
} {0 {}}
do_test auth-1.78 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1}
}
@@ -632,7 +632,7 @@ ifcapable tempdb {
set ::authargs
} {v1 {} temp {}}
do_test auth-1.90 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1}
}
@@ -779,7 +779,7 @@ ifcapable tempdb {
}
} {1 {not authorized}}
do_test auth-1.113 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1 v1}
do_test auth-1.114 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -823,7 +823,7 @@ ifcapable tempdb {
set ::authargs
} {v1 {} temp {}}
do_test auth-1.121 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1 v1}
do_test auth-1.122 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -980,7 +980,7 @@ do_test auth-1.139 {
set ::authargs
} {r1 t1 temp {}}
do_test auth-1.140 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1}
do_test auth-1.141 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -1016,7 +1016,7 @@ do_test auth-1.144 {
set ::authargs
} {r1 t1 temp {}}
do_test auth-1.145 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1}
do_test auth-1.146 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -1052,7 +1052,7 @@ do_test auth-1.149 {
set ::authargs
} {r1 t1 temp {}}
do_test auth-1.150 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1 r1}
do_test auth-1.151 {
@@ -1142,7 +1142,7 @@ do_test auth-1.164 {
catchsql {DROP TRIGGER r1}
} {1 {not authorized}}
do_test auth-1.165 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1 r1}
do_test auth-1.166 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -1170,7 +1170,7 @@ do_test auth-1.169 {
catchsql {DROP TRIGGER r1}
} {0 {}}
do_test auth-1.170 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1 r1}
do_test auth-1.171 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -1202,7 +1202,7 @@ do_test auth-1.175 {
set ::authargs
} {r1 t1 temp {}}
do_test auth-1.176 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1}
} ;# ifcapable trigger
@@ -1306,7 +1306,7 @@ ifcapable tempdb {
catchsql {CREATE INDEX i1 ON t1(b)}
} {1 {not authorized}}
do_test auth-1.194 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1}
do_test auth-1.195 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -1350,7 +1350,7 @@ ifcapable tempdb {
set ::authargs
} {i1 t1 temp {}}
do_test auth-1.202 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1 i1}
}
@@ -1466,7 +1466,7 @@ ifcapable tempdb {
catchsql {DROP INDEX i1}
} {0 {}}
do_test auth-1.222 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1 i1}
do_test auth-1.223 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -1482,7 +1482,7 @@ ifcapable tempdb {
set ::authargs
} {i1 t1 temp {}}
do_test auth-1.225 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1 i1}
do_test auth-1.226 {
proc auth {code arg1 arg2 arg3 arg4 args} {
@@ -1498,7 +1498,7 @@ ifcapable tempdb {
set ::authargs
} {i1 t1 temp {}}
do_test auth-1.228 {
execsql {SELECT name FROM sqlite_temp_master}
execsql {SELECT name FROM temp.sqlite_master}
} {t1}
}
@@ -1765,7 +1765,7 @@ ifcapable attach {
}
} {0 {}}
do_test auth-1.267 {
execsql {SELECT name FROM sqlite_temp_master WHERE type='table'}
execsql {SELECT name FROM temp.sqlite_master WHERE type='table'}
} {t1x}
do_test auth-1.268 {
set authargs
@@ -2070,7 +2070,7 @@ ifcapable {altertable} {
}
} {1 {not authorized}}
do_test auth-1.307 {
set x [execsql {SELECT sql FROM sqlite_temp_master WHERE type='t5'}]
set x [execsql {SELECT sql FROM temp.sqlite_master WHERE type='t5'}]
regexp new_col_3 $x
} {0}
@@ -2373,7 +2373,7 @@ ifcapable compound&&subquery {
do_test auth-5.2 {
execsql {
SELECT name FROM (
SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master)
SELECT * FROM sqlite_master UNION ALL SELECT * FROM temp.sqlite_master)
WHERE type='table'
ORDER BY name
}
+1 -1
View File
@@ -122,7 +122,7 @@ do_execsql_test auth3-3.0 {
key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,
value TEXT NOT NULL ON CONFLICT FAIL);
ALTER TABLE TempTable RENAME TO DoNotRead;
SELECT name FROM sqlite_temp_master;
SELECT name FROM temp.sqlite_master;
} {DoNotRead sqlite_autoindex_DoNotRead_1}
finish_test
+1 -1
View File
@@ -344,7 +344,7 @@ ifcapable tempdb {
do_test autoinc-4.1 {
execsql {
SELECT 1, name FROM sqlite_master WHERE type='table';
SELECT 2, name FROM sqlite_temp_master WHERE type='table';
SELECT 2, name FROM temp.sqlite_master WHERE type='table';
}
} {1 sqlite_sequence}
do_test autoinc-4.2 {
-1
View File
@@ -172,4 +172,3 @@ do_execsql_test 3.1 { CREATE VIRTUAL TABLE t3 USING tcl('vvv_command') }
do_execsql_test 3.2 { CREATE VIRTUAL TABLE t4 USING tcl('yyy_command') }
finish_test
-1
View File
@@ -118,4 +118,3 @@ for {set param1 0} {$param1<16} {incr param1} {
}
finish_test
+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;
}
+1 -1
View File
@@ -45,7 +45,7 @@ proc list_all_views {{db db}} {
set res [list]
$db eval { PRAGMA database_list } {
set tbl "$name.sqlite_master"
if {$name == "temp"} { set tbl sqlite_temp_master }
if {$name == "temp"} { set tbl temp.sqlite_master }
set sql "SELECT '$name.' || name FROM $tbl WHERE type = 'view'"
lappend res {*}[$db eval $sql]
+2 -2
View File
@@ -1062,7 +1062,7 @@ ifcapable altertable {
PRAGMA foreign_keys = off;
ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
PRAGMA foreign_keys = on;
SELECT sql FROM sqlite_temp_master WHERE name='t2';
SELECT sql FROM temp.sqlite_master WHERE name='t2';
}
} {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
@@ -1093,7 +1093,7 @@ ifcapable altertable {
]
do_test fkey2-14.2tmp.2.2 {
execsql { ALTER TABLE t1 RENAME TO t4 }
execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'}
execsql { SELECT sql FROM temp.sqlite_master WHERE type = 'table'}
} [list \
{CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \
{CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \
+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
-1
View File
@@ -107,4 +107,3 @@ do_test 4.4 {
close $blob
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
+1 -1
View File
@@ -42,7 +42,7 @@ do_test intarray-1.1 {
set ia3 [sqlite3_intarray_create db ia3]
set ia4 [sqlite3_intarray_create db ia4]
db eval {
SELECT type, name FROM sqlite_temp_master
SELECT type, name FROM temp.sqlite_master
ORDER BY name
}
} {table ia1 table ia2 table ia3 table ia4}
+2 -2
View File
@@ -128,7 +128,7 @@ ifcapable tempdb {
} {1 interrupted}
do_test interrupt-3.$i.3 {
execsql {
SELECT name FROM sqlite_temp_master;
SELECT name FROM temp.sqlite_master;
}
} {}
do_test interrupt-3.$i.4 {
@@ -139,7 +139,7 @@ ifcapable tempdb {
do_test interrupt-3.$i.5 {
catchsql {SELECT name FROM sqlite_temp_master};
execsql {
SELECT name FROM sqlite_temp_master;
SELECT name FROM temp.sqlite_master;
}
} {}
}
+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;
-1
View File
@@ -122,4 +122,3 @@ do_execsql_test 3.0 {
finish_test
+18 -2
View File
@@ -315,7 +315,23 @@ 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}}
finish_test
-1
View File
@@ -299,4 +299,3 @@ do_execsql_test 7.3 {
finish_test
-1
View File
@@ -69,4 +69,3 @@ do_faultsim_test 6 -faults oom* -body {
}
finish_test
+1 -1
View File
@@ -149,7 +149,7 @@ ifcapable altertable {
} {}
do_execsql_test schema4-2.8 {
select sql from sqlite_temp_master WHERE type='table';
select sql from temp.sqlite_master WHERE type='table';
} {{CREATE TABLE x1(x)}}
do_execsql_test schema4-2.7 { ALTER TABLE tbl RENAME TO tbl2 } {}
+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
+101
View File
@@ -0,0 +1,101 @@
# 2016 December 15
#
# 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 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
forcedelete test.db test.db-journal test.db-wal
foreach {tn schema output} {
1 {
CREATE TABLE p1(a PRIMARY KEY, b);
CREATE TABLE c1(x, y REFERENCES p1);
} {
CREATE INDEX 'c1_y' ON 'c1'('y'); --> p1(a)
}
2 {
CREATE TABLE p1(a PRIMARY KEY, b);
CREATE TABLE c2(x REFERENCES p1, y REFERENCES p1);
} {
CREATE INDEX 'c2_y' ON 'c2'('y'); --> p1(a)
CREATE INDEX 'c2_x' ON 'c2'('x'); --> p1(a)
}
3 {
CREATE TABLE 'p 1'(a, b, c, PRIMARY KEY(c, b));
CREATE TABLE 'c 1'(x, y, z, FOREIGN KEY (z, y) REFERENCES 'p 1');
} {
CREATE INDEX 'c 1_z_y' ON 'c 1'('z', 'y'); --> p 1(c,b)
}
4 {
CREATE TABLE p1(a, 'b b b' PRIMARY KEY);
CREATE TABLE c1('x y z' REFERENCES p1);
CREATE INDEX i1 ON c1('x y z') WHERE "x y z" IS NOT NULL;
} {
}
5 {
CREATE TABLE p1(a, 'b b b' PRIMARY KEY);
CREATE TABLE c1('x y z' REFERENCES p1);
CREATE INDEX i1 ON c1('x y z') WHERE "x y z" IS NOT 12;
} {
CREATE INDEX 'c1_x y z' ON 'c1'('x y z'); --> p1(b b b)
}
6 {
CREATE TABLE x1(a, b, c, UNIQUE(a, b));
CREATE TABLE y1(a, b, c, FOREIGN KEY(b, a) REFERENCES x1(a, b));
CREATE INDEX y1i ON y1(a, c, b);
} {
CREATE INDEX 'y1_b_a' ON 'y1'('b', 'a'); --> x1(a,b)
}
6 {
CREATE TABLE x1(a COLLATE nocase, b, UNIQUE(a));
CREATE TABLE y1(a COLLATE rtrim REFERENCES x1(a));
} {
CREATE INDEX 'y1_a' ON 'y1'('a' COLLATE nocase); --> x1(a)
}
} {
forcedelete test.db
sqlite3 db test.db
execsql $schema
set expected ""
foreach line [split $output "\n"] {
set line [string trim $line]
if {$line!=""} {
append expected "$line\n"
}
}
do_test 1.$tn.1 {
set RES [catchcmd test.db [list .lint fkey-indexes]]
} [list 0 [string trim $expected]]
do_test 1.$tn.2 {
execsql [lindex $RES 1]
catchcmd test.db [list .lint fkey-indexes]
} {0 {}}
db close
}
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
-2
View File
@@ -198,5 +198,3 @@ do_test 4.7 {
} {1 SQLITE_ERROR}
finish_test
-1
View File
@@ -74,4 +74,3 @@ do_execsql_test 1.4 {
} {1 1 1}
finish_test
+1 -1
View File
@@ -236,7 +236,7 @@ do_test 5.1 {
do_execsql_test 5.2 {
SELECT * FROM sqlite_master;
SELECT * FROM sqlite_temp_master;
SELECT * FROM temp.sqlite_master;
} {
trigger tr1 t1 0
{CREATE TRIGGER tr1 BEFORE INSERT ON t1 BEGIN SELECT 1,2,3; END}
+2 -2
View File
@@ -23,7 +23,7 @@ source $testdir/tester.tcl
do_test tkt3630-1 {
db eval {
CREATE TEMP TABLE temp1(a,b,c);
SELECT * FROM sqlite_temp_master WHERE sql GLOB '*TEMP*';
SELECT * FROM temp.sqlite_master WHERE sql GLOB '*TEMP*';
}
} {}
do_test tkt3630-2 {
@@ -39,7 +39,7 @@ ifcapable altertable {
db eval {
ALTER TABLE temp2 ADD COLUMN d;
ALTER TABLE temp2 RENAME TO temp2rn;
SELECT name FROM sqlite_temp_master WHERE name LIKE 'temp2%';
SELECT name FROM temp.sqlite_master WHERE name LIKE 'temp2%';
}
} {temp2rn}
}
+1 -1
View File
@@ -62,7 +62,7 @@ do_test tkt3810-3 {
# an orphan.
#
do_test tkt3810-4 {
execsql {SELECT name FROM sqlite_temp_master ORDER BY name}
execsql {SELECT name FROM temp.sqlite_master ORDER BY name}
} {r1}
# Because it is an orphan, it cannot be dropped.
+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
+2 -2
View File
@@ -1031,7 +1031,7 @@ ifcapable altertable {
PRAGMA foreign_keys = off;
ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
PRAGMA foreign_keys = on;
SELECT sql FROM sqlite_temp_master WHERE name='t2';
SELECT sql FROM temp.sqlite_master WHERE name='t2';
}
} {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
@@ -1064,7 +1064,7 @@ ifcapable altertable {
]
do_test without_rowid3-14.2tmp.2.2 {
execsql { ALTER TABLE t1 RENAME TO t4 }
execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'}
execsql { SELECT sql FROM temp.sqlite_master WHERE type = 'table'}
} [list \
{CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid} \
{CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)
+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;
+3 -2
View File
@@ -495,7 +495,7 @@ puts $fd "\175;"
# Generate the lookup table
#
puts $fd "\n/* Definitions of all built-in pragmas */"
puts $fd "static const struct sPragmaNames \173"
puts $fd "typedef struct PragmaName \173"
puts $fd " const char *const zName; /* Name of pragma */"
puts $fd " u8 ePragTyp; /* PragTyp_XXX value */"
puts $fd " u8 mPragFlg; /* Zero or more PragFlg_XXX values */"
@@ -503,7 +503,8 @@ puts $fd { u8 iPragCName; /* Start of column names in pragCName[] */}
puts $fd " u8 nPragCName; \
/* Num of col names. 0 means use pragma name */"
puts $fd " u32 iArg; /* Extra argument */"
puts $fd "\175 aPragmaNames\[\] = \173"
puts $fd "\175 PragmaName;"
puts $fd "static const PragmaName aPragmaName\[\] = \173"
set current_if {}
set spacer [format { %26s } {}]