Index: pages/download.in
==================================================================
--- pages/download.in
+++ pages/download.in
@@ -1,6 +1,8 @@
Index: pages/faq.in
==================================================================
--- pages/faq.in
+++ pages/faq.in
@@ -217,13 +217,15 @@
the text of the original CREATE TABLE or CREATE INDEX statement that
created the table or index. For automatically created indices (used
to implement the PRIMARY KEY or UNIQUE constraints) the sql field
is NULL.
- The SQLITE_MASTER table is read-only. You cannot change this table
- using UPDATE, INSERT, or DELETE. The table is automatically updated by
- CREATE TABLE, CREATE INDEX, DROP TABLE, and DROP INDEX commands.
+ The SQLITE_MASTER table cannot be modified using UPDATE, INSERT,
+ or DELETE (except under
+ [PRAGMA writable_schema|extraordinary conditions]).
+ The SQLITE_MASTER table is automatically updated by commands like
+ CREATE TABLE, CREATE INDEX, DROP TABLE, and DROP INDEX.
Temporary tables do not appear in the SQLITE_MASTER table. Temporary
tables and their indices and triggers occur in another special table
named SQLITE_TEMP_MASTER. SQLITE_TEMP_MASTER works just like SQLITE_MASTER
except that it is only visible to the application that created the
Index: pages/index.in
==================================================================
--- pages/index.in
+++ pages/index.in
@@ -1,6 +1,8 @@
SQLite Home Page
+
+hd_adunit
Index: pages/lang.in
==================================================================
--- pages/lang.in
+++ pages/lang.in
@@ -627,15 +627,16 @@
RecursiveBubbleDiagram commit-stmt
RecursiveBubbleDiagram rollback-stmt
-^No changes can be made to the database except within a transaction.
-^Any command that changes the database (basically, any SQL command
-other than [SELECT]) will automatically start a transaction if
+^No reads or writes occur except within a transaction.
+^Any command that accesses the database (basically, any SQL command,
+except a few [PRAGMA] statements)
+will automatically start a transaction if
one is not already in effect. ^Automatically started transactions
-are committed when the last query finishes.
+are committed when the last SQL statement finishes.
^Transactions can be started manually using the BEGIN
command. ^(Such transactions usually persist until the next
@@ -659,47 +660,97 @@
a transaction will fail with an error, regardless of whether
the transaction was started by [SAVEPOINT] or a prior BEGIN.
^The COMMIT command and the ROLLBACK command without the TO clause
work the same on [SAVEPOINT] transactions as they do with transactions
started by BEGIN.
+
+Read transactions versus write transactions
+
+SQLite current supports multiple simultaneous read transactions
+coming from separate database connections, possibly in separate
+threads or processes, but only one simultaneous write transaction.
+
+
+
A read transaction is used for reading only. A write transaction
+allows both reading and writing. A read transaction is started
+by a SELECT statement, and a write transaction is started by
+statements like CREATE, DELETE, DROP, INSERT, or UPDATE (collectively
+"write statements"). If a write statement occurs while
+a read transaction is active, then the read transaction is upgraded
+to write transaction if possible. If some other database connection
+has already modified the database or is already in the process of
+modifying the database, then upgrading to a write transaction is
+not possible and the write statement will fail with [SQLITE_BUSY].
+
+
+
+While a read transaction is active, any changes to the database that
+are implemented by separate database connections will not be seen
+by the database connection that started the read transaction. If database
+connection X is holding a read transaction, it is possible that some
+other database connection Y might change the content of the database
+while X's transaction is still open, however X will not be able to see
+those changes until after the transaction ends. While its read
+transaction is active, X will continue to see an historic snapshot
+the database prior to the changes implemented by Y.
+
+
hd_fragment immediate {BEGIN IMMEDIATE} {BEGIN EXCLUSIVE}
+DEFERRED, IMMEDIATE, and EXCLUSIVE transactions
+
+
+^Transactions can be DEFERRED, IMMEDIATE, or EXCLUSIVE.
+^The default transaction behavior is DEFERRED.
+
+
+
+^DEFERRED means that the transaction does not actually
+start until the database is first accessed. ^Internally,
+the BEGIN DEFERRRED statement merely sets a flag on the database
+connection that turns off the automatic commit that would normally
+occur when the last statement finishes. This causes the transaction
+that is automatically started to persist until an explicit
+COMMIT or ROLLBACK or until a rollback is provoked by an error
+or an ON CONFLICT ROLLBACK clause. If the first statement after
+BEGIN DEFERRED is a SELECT, then a read transaction is started.
+Subsequent write statements will upgrade the transaction to a
+write transaction if possible, or return SQLITE_BUSY. If the
+first statement after BEGIN DEFERRED is a write statement, then
+a write transaction is started.
+
+
+
+^IMMEDIATE cause the database connection to start a new write
+immediately, without waiting for a writes statement. The
+BEGIN IMMEDIATE might fail with [SQLITE_BUSY] if another write
+transaction is already active on another database connection.
+
+
-^Transactions can be deferred, immediate, or exclusive.
-^The default transaction behavior is deferred.
-^Deferred means that no locks are acquired
-on the database until the database is first accessed. ^Thus with a
-deferred transaction, the BEGIN statement itself does nothing to the
-filesystem. ^Locks
-are not acquired until the first read or write operation. ^The first read
-operation against a database creates a [SHARED] lock and the first
-write operation creates a [RESERVED] lock. ^Because the acquisition of
-locks is deferred until they are needed, it is possible that another
-thread or process could create a separate transaction and write to
-the database after the BEGIN on the current thread has executed.
-^If the transaction is immediate, then [RESERVED] locks
-are acquired on all databases as soon as the BEGIN command is
-executed, without waiting for the
-database to be used. ^After a BEGIN IMMEDIATE,
-no other [database connection] will be able to write to the database or
-do a BEGIN IMMEDIATE or BEGIN EXCLUSIVE. ^Other processes can continue
-to read from the database, however. ^An exclusive transaction causes
-[EXCLUSIVE] locks to be acquired on all databases. ^After a BEGIN
-EXCLUSIVE, no other [database connection] except for [read_uncommitted]
-connections will be able to read the database and no other connection without
-exception will be able to write the database until the transaction is
-complete.
+^EXCLUSIVE is similar to IMMEDIATE in that a write transaction
+is started immediately. EXCLUSIVE and IMMEDIATE are the same
+in [WAL mode], but in other journaling modes, EXCLUSIVE prevents
+other database connections from reading the database while the
+transaction is underway.
+Implicit versus explicit transactions
+
-^(An implicit transaction (a transaction that is started automatically,
+An implicit transaction (a transaction that is started automatically,
not a transaction started by BEGIN) is committed automatically when
the last active statement finishes. A statement finishes when its
+last cursor closes, which is guaranteed to happen when the
prepared statement is [sqlite3_reset() | reset] or
-[sqlite3_finalize() | finalized]. An open [sqlite3_blob] used for
-incremental BLOB I/O counts as an unfinished statement. The [sqlite3_blob]
-finishes when it is [sqlite3_blob_close() | closed].)^
+[sqlite3_finalize() | finalized]. Some statements might "finish"
+for the purpose of transaction control prior to being reset or finalized,
+but there is no guarantee of this. The only way to ensure that a
+statement has "finished" is to invoke [sqlite3_reset()] or
+[sqlite3_finalize()] on that statement. An open [sqlite3_blob] used for
+incremental BLOB I/O also counts as an unfinished statement.
+The [sqlite3_blob] finishes when it is [sqlite3_blob_close() | closed].
^The explicit COMMIT command runs immediately, even if there are
pending [SELECT] statements. ^However, if there are pending
@@ -707,12 +758,12 @@
will fail with an error code [SQLITE_BUSY].
^An attempt to execute COMMIT might also result in an [SQLITE_BUSY] return code
-if an another thread or process has a [shared lock] on the database
-that prevented the database from being updated. ^When COMMIT fails in this
+if an another thread or process has an open read connection.
+^When COMMIT fails in this
way, the transaction remains active and the COMMIT can be retried later
after the reader has had a chance to clear.
@@ -1924,13 +1975,40 @@
[virtual machine instructions] it would have used to execute the command had
the EXPLAIN keyword not been present. ^When the EXPLAIN QUERY PLAN phrase
appears, the statement returns high-level information regarding the query
plan that would have been used.
-The EXPLAIN QUERY PLAN command is described in
+
The EXPLAIN QUERY PLAN command is described in
[explain query plan|more detail here].
+
EXPLAIN operates at run-time, not at prepare-time
+
+The EXPLAIN and EXPLAIN QUERY PLAN prefixes affect the behavior of
+running a [prepared statement] using [sqlite3_step()]. The process of
+generating a new prepared statement using [sqlite3_prepare()] or similar
+is (mostly) unaffected by EXPLAIN. (The exception to the previous sentence
+is that some special opcodes used by EXPLAIN QUERY PLAN are omitted when
+building an EXPLAIN QUERY PLAN prepared statement, as a performance
+optimization.)
+
+
This means that actions that occur during sqlite3_prepare() are
+unaffected by EXPLAIN.
+
+
+
+Some [PRAGMA] statements do their work during sqlite3_prepare() rather
+than during sqlite3_step(). Those PRAGMA statements are unaffected
+by EXPLAIN. They operate the same with or without the EXPLAIN prefix.
+The set of PRAGMA statements that are unaffected by EXPLAIN can vary
+from one release to the next. Some PRAGMA statements operate during
+sqlite3_prepare() depending on their arguments. For consistent
+results, avoid using EXPLAIN on PRAGMA statements.
+
+
+The [authorizer callback] is invoked regardless of the presence of
+EXPLAIN or EXPLAIN QUERY PLAN.
+
##############################################################################
Section expression expr {*expression {expression syntax}}
RecursiveBubbleDiagram expr
Index: pages/pragma.in
==================================================================
--- pages/pragma.in
+++ pages/pragma.in
@@ -106,10 +106,12 @@
internal (non-table) data. The PRAGMA statement is issued using the same
interface as other SQLite commands (e.g. [SELECT], [INSERT]) but is
different in the following important respects:
+- The pragma command is specific to SQLite and is
+ not compatible with any other SQL database engine.
- Specific pragma statements may be removed and others added in future
releases of SQLite. There is no guarantee of backwards compatibility.
- ^No error messages are generated if an unknown pragma is issued.
Unknown pragmas are simply ignored. This means if there is a typo in
a pragma statement the library does not inform the user of the fact.
@@ -120,12 +122,15 @@
not during the [sqlite3_step()] call as normal SQL statements do.
^Or the pragma might run during sqlite3_step() just like normal
SQL statements. Whether or not the pragma runs during sqlite3_prepare()
or sqlite3_step() depends on the pragma and on the specific release
of SQLite.
-
- The pragma command is specific to SQLite and is
- not compatible with any other SQL database engine.
+
- The [EXPLAIN] and [EXPLAIN QUERY PLAN] prefixes to SQL statements
+ only affect the behavior of the statement during [sqlite3_step()].
+ That means that PRAGMA statements that take effect during
+ [sqlite3_prepare()] will behave the same way regardless of whether or
+ not they are prefaced by "EXPLAIN".
The C-language API for SQLite provides the [SQLITE_FCNTL_PRAGMA]
[sqlite3_file_control | file control] which gives [VFS] implementations the
opportunity to add new PRAGMA statements or to override the meaning of
@@ -560,25 +565,25 @@
}
Pragma encoding {
^(PRAGMA encoding;
-
PRAGMA encoding = "UTF-8";
-
PRAGMA encoding = "UTF-16";
-
PRAGMA encoding = "UTF-16le";
-
PRAGMA encoding = "UTF-16be";)^
+
PRAGMA encoding = 'UTF-8';
+
PRAGMA encoding = 'UTF-16';
+
PRAGMA encoding = 'UTF-16le';
+
PRAGMA encoding = 'UTF-16be';)^
^In first form, if the main database has already been
created, then this pragma returns the text encoding used by the
- main database, one of "UTF-8", "UTF-16le" (little-endian UTF-16
- encoding) or "UTF-16be" (big-endian UTF-16 encoding). ^If the main
+ main database, one of 'UTF-8', 'UTF-16le' (little-endian UTF-16
+ encoding) or 'UTF-16be' (big-endian UTF-16 encoding). ^If the main
database has not already been created, then the value returned is the
text encoding that will be used to create the main database, if
it is created by this session.
^The second through fifth forms of this pragma
set the encoding that the main database will be created with if
- it is created by this session. ^The string "UTF-16" is interpreted
+ it is created by this session. ^The string 'UTF-16' is interpreted
as "UTF-16 encoding using native machine byte-ordering". ^It is not
possible to change the text encoding of a database after it has been
created and any attempt to do so will be silently ignored.
^Once an encoding has been set for a database, it cannot be changed.
@@ -1845,11 +1850,11 @@
DISCLAIMER
} SQLITE_INTROSPECTION_PRAGMAS
Section {List Of PRAGMAs} {toc} {{pragma list}}
set lx {}
-foreach prag [array names PragmaRef] {
+foreach prag [array names PragmaKeys] {
set ref $PragmaRef($prag)
if {[info exists PragmaLegacy($prag)]} {
lappend lx [list "PRAGMA $ref" $prag 3]
} elseif {[info exists PragmaDebug($prag)]} {
lappend lx [list "PRAGMA $ref" $prag 4]
Index: pages/testing.in
==================================================================
--- pages/testing.in
+++ pages/testing.in
@@ -11,45 +11,49 @@
#
# NOTE: Also update the version number in the text!!!
#
# sloc sqlite3.c
-set stat(coreSLOC) 128906 ;# Non-comment lines of amalgamation code
+set stat(coreSLOC) 138858 ;# Non-comment lines of amalgamation code
# sloc test*.c
-set stat(tclcSLOC) 26088 ;# Non-comment lines of test C code
+set stat(tclcSLOC) 26873 ;# Non-comment lines of test C code
# ls test*.c tclsqlite.c | wc
-set stat(tclcNfile) 48 ;# Number of files of TCL C testcode + tclsqlite.c
+set stat(tclcNfile) 50 ;# Number of files of TCL C testcode + tclsqlite.c
# ls -l test*.c tclsqlite.c | awk '{sum+=$5}END{print sum}'
-set stat(tclcNByte) 1212234 ;# Number of bytes of TCL C testcode + tclsqlite.c
+set stat(tclcNByte) 1245032 ;# Number of bytes of TCL C testcode + tclsqlite.c
# sloc `find . -name '*.test' -print` test/*.tcl
-set stat(tclsSLOC) 462686 ;# Non-comment lines of TCL test script
+set stat(tclsSLOC) 480305 ;# Non-comment lines of TCL test script
# ls `find . -name '*.test' -print` test/*.tcl | wc
-set stat(tclsNFile) 1307 ;# Number of files of TCL test script
+set stat(tclsNFile) 1264 ;# Number of files of TCL test script
# wc `find . -name '*.test' -print` test/*.tcl
-set stat(tclsNByte) 16214472 ;# Number of bytes of TCL test script
+set stat(tclsNByte) 21545154 ;# Number of bytes of TCL test script
# cat `find . -name '*.test' -print` | egrep 'do[_a-z]*_test' | wc
-set stat(tclNTest) 40870 ;# Number of test cases in the TCL test suite
-set stat(tclNEval) 2514125 ;# Number of test case evaluations (fulltest)
+set stat(tclNTest) 44792 ;# Number of test cases in the TCL test suite
+set stat(tclNEval) 11291041 ;# Number of test case evaluations (releasetest)
# grep fuzz device_one/test-out.txt | wc
set stat(nSqlFuzz) 111268 ;# Number of SQL fuzz tests
-set stat(vqNEval) 142597 ;# Number of test evaluations for veryquick.test
+set stat(vqNEval) 248537 ;# Number of test evaluations for veryquick.test
# set stat(vqStmtCov) 97.23 ;# veryquick statement coverage
# set stat(vqBrCov) 92.57 ;# veryquick branch coverage
# set stat(allStmtCov) 99.50 ;# all.test statement coverage
# set stat(allBrCov) 97.41 ;# all.test condition/decision coverage
# tclsh mkth3.tcl cfg/*.cfg */*.test >th3.c; sloc th3.c
-set stat(th3SLOC) 792338 ;# Non-comment lines in full th3.c
+set stat(th3SLOC) 948149 ;# Non-comment lines in full th3.c
# ls -l th3.c
-set stat(th3NByte) 57927541 ;# Number of bytes in full th3.c
+set stat(th3NByte) 69393976 ;# Number of bytes in full th3.c
# grep th3testCheck */*.test |wc
# grep '^--result' */*.test | wc
# grep '^--glob' */*.test | wc
# grep '^--notglob' */*.test | wc
# grep '^--eqp' */*.test | wc
-set stat(th3NTest) 43049 ;# Number of test cases
+# grep '^--tableresult' */*.test | wc
+# grep '^--anyglob' */*.test | wc
+# grep '^--sort-check' */*.test | wc
+# grep '^--cklog' */*.test | wc
+set stat(th3NTest) 44753 ;# Number of test cases
# from output of a min.rc test run.
-set stat(th3NECov) 1614390 ;# Number of test case evals for coverage
+set stat(th3NECov) 1683889 ;# Number of test case evals for coverage
#set stat(th3NETest) 7247055 ;# Number of test case evaluations
#set stat(th3NEExt) 589175483 ;# Number of test case evals extended
#set stat(th3NERel) 2500000000 ;# Number of test case evals release
set stat(th3StmtCov) 100.00 ;# TH3 statement coverage
set stat(th3BrCov) 100.00 ;# TH3 branch coverage
@@ -64,13 +68,13 @@
# grep '^query' `fossil ls | awk '/\.test$/{print $2}'` | wc
set stat(sltNTest) 7195342 ;# Number of test cases in SLT
# grep 'errors out of' all-out.txt | awk '{x+=$5}END{print x}'
set stat(sltNRun) 11879758 ;# Number of tests run in SLT
# grep 'assert(' sqlite3.c | wc
-set stat(nAssert) 5415 ;# Number of assert statements
+set stat(nAssert) 5665 ;# Number of assert statements
# grep 'testcase(' sqlite3.c | grep -v define | wc
-set stat(nTestcase) 878 ;# Number of testcase statements
+set stat(nTestcase) 992 ;# Number of testcase statements
set stat(totalSLOC) [expr {$stat(tclcSLOC)+$stat(tclsSLOC)+
$stat(th3SLOC)+$stat(sltcSLOC)+$stat(sltsSLOC)}]
proc GB {expr} {
@@ -105,11 +109,11 @@
Introduction
The reliability and robustness of SQLite is achieved in part
by thorough and careful testing.
-As of [version 3.23.0] ([dateof:3.23.0]),
+
As of [version 3.29.0] ([dateof:3.29.0]),
the SQLite library consists of approximately
KB {$stat(coreSLOC)} KSLOC of C code.
(KSLOC means thousands of "Source Lines Of Code" or, in other words,
lines of code excluding blank lines and comments.)
By comparison, the project has
@@ -371,11 +375,11 @@
The SQL fuzz generator tests are part of the TCL test suite.
During a full test run, about KB {$stat(nSqlFuzz)}
thousand fuzz SQL statements are
generated and tested.
-hd_fragment aflfuzz {American Fuzzy Lop fuzzer}
+hd_fragment aflfuzz {American Fuzzy Lop fuzzer} {AFL}
SQL Fuzz Using The American Fuzzy Lop Fuzzer
The American Fuzzy Lop
or "AFL" fuzzer is a recent (circa 2014) innovation from Michal Zalewski.
Unlike most other fuzzers that blindly generate random inputs, the AFL
@@ -400,10 +404,13 @@
instrumentation has narrowed them down to less than 50,000 test cases that
cover all distinct behaviors. Newly discovered test cases are periodically
captured and added to the [TCL test suite] where they can be rerun using
the "make fuzztest" or "make valgrindfuzz" commands.
+
Update: As of SQLite [version 3.29.0] ([dateof:3.29.0]) the use of
+AFL has been superceded by the new [dbsqlfuzz] fuzzer described below.
+
hd_fragment ossfuzz {OSS Fuzz}
Google OSS Fuzz
Beginning in 2016, a team of engineers at Google started the
[https://github.com/google/oss-fuzz|OSS Fuzz] project.
@@ -414,10 +421,46 @@
and emails a confirmation to the developers.
SQLite is one of many open-source projects that OSS Fuzz tests. The
[https://www.sqlite.org/src/file/test/ossfuzz.c|test/ossfuzz.c] source file
in the SQLite repository is SQLite's interface to OSS fuzz.
+
+hd_fragment dbsqlfuzz {dbsqlfuzz}
+
The dbsqlfuzz fuzzer
+
+Beginning in late 2018, SQLite has been fuzzed using a new proprietary
+fuzzer called "dbsqlfuzz". Dbsqlfuzz is built using the
+[http://llvm.org/docs/LibFuzzer.html|libFuzzer] framework of LLVM.
+
+
The dbsqlfuzz fuzzer mutates both the SQL input and the database file
+at the same time. Dbsqlfuzz uses a custom
+[https://github.com/google/fuzzer-test-suite/blob/master/tutorial/structure-aware-fuzzing.md|Structure-Aware Mutator]
+on a specialized input file that defines both an input database and SQL
+text to be run against that database. Because it mutates both the input
+database and the input SQL at the same time, dbsqlfuzz has been able to
+find some obscure faults in SQLite that were missed by prior fuzzers that
+mutated only SQL inputs or only the database file.
+
+
As of this writing (2019-07-16), the SQLite developers have stopped
+using AFL for routine testing and instead are focused on running
+dbsqlfuzz. At least one instance of dbsqlfuzz is running on the latest
+SQLite source code at all times, in order to catch any new problems that
+might be introduced into the source tree as features are added and routine
+maintenance is performed.
+
+hd_fragment fuzzcheck fuzzcheck
+
The fuzzcheck test harness
+
+Historical test cases from [AFL], [OSS Fuzz], and [dbsqlfuzz] are
+collected in a set of database files in the main SQLite source tree
+and then rerun by the "fuzzcheck" utility program whenever one runs
+"make test". Fuzzcheck only runs a few thousand "interesting" cases
+out of the hundreds of millions of cases that the various fuzzers have
+examined over the years. "Interesting" cases are cases that exhibit
+previously unseen behavior. Actual bugs found by fuzzers are always
+included among the interesting test cases, but most of the cases run
+by fuzzcheck were never actual bugs.
Malformed Database Files
There are numerous test cases that verify that SQLite is able to
deal with malformed database files.
@@ -816,10 +859,13 @@
asserts are so numerous and are in such performance critical places, that
the database engine runs about three times slower when asserts are enabled.
Hence, the default (production) build of SQLite disables asserts.
Assert statements are only enabled when SQLite is compiled with the
SQLITE_DEBUG preprocessor macro defined.
+
+See the [The Use Of assert In SQLite|Use Of assert in SQLite] document
+for additional information about how SQLite uses assert().
b
hd_fragment valgrind
Valgrind
[http://valgrind.org/ | Valgrind] is perhaps the most amazing
Index: wrap.tcl
==================================================================
--- wrap.tcl
+++ wrap.tcl
@@ -751,10 +751,27 @@
set ::${varname}($rn) [list $hd_req_rdr(derived) $b $c]
lappend ::${varname}(*) $rn
}
hd_reset_requirement_reader
}
+
+# If the filed "adunit.txt" exists in the working
+# directory, then insert a verbatim copy of the
+# text of that file whenever the hd_adunit routine
+# is seen. If the file does not exist or is not
+# readable, then hd_adunit is a no-op.
+#
+if {[file readable adunit.txt]} {
+ set fd [open adunit.txt]
+ set ADUNIT [read $fd]
+ close $fd
+ proc hd_adunit {} {
+ hd_puts $::ADUNIT
+ }
+} else {
+ proc hd_adunit {} {}
+}
# First pass. Process all files. But do not render hyperlinks.
# Merely collect keyword information so that hyperlinks can be
# correctly rendered on the second pass.
#