# page_content

c2: Row Values
c3: 4. Backwards Compatibility
c5: rowvalue.html#backwards_compatibility
c4:
Row values were added to SQLite
version 3.15.0 (2016-10-14).  Attempts to use row values in
prior versions of SQLite will generate syntax errors.
This page last modified on  2022-03-07 15:31:00 UTC


c2: How To Compile SQLite
c3: Overview
c5: howtocompile.html#overview
c4:
SQLite is ANSI-C source code.
It must be compiled into machine code before it is useful.
This article is a guide to the various ways of compiling SQLite.


This article does not contain a step-by-step recipe for compiling
SQLite.  That would be difficult since each development situation
is different.
Rather, this article describes and illustrates the principals behind the
compilation of SQLite.  Typical compilation commands are provided as examples
with the expectation that application developers can use these examples
as guidance for developing their own custom compilation procedures.
In other words, this article provides ideas and insights, not turnkey
solutions.


c2: How To Compile SQLite
c3: 1. Amalgamation Versus Individual Source Files
c5: howtocompile.html#amalgamation_versus_individual_source_files
c4:
SQLite is built from over one hundred files of C code and script
spread across multiple directories.  The implementation of SQLite is pure
ANSI-C, but many of the C-language source code files are either
generated or transformed by auxiliary C programs and AWK, SED, and TCL 
scripts prior to being incorporated into the finished SQLite library.
Building the necessary C programs and transforming and/or creating the
C-language source code for SQLite is a complex process.

To simplify matters, SQLite is also available as a pre-packaged
amalgamation source code file: sqlite3.c.  The amalgamation is
a single file of ANSI-C code that implements the entire SQLite library.
The amalgamation is much easier to deal with.  Everything is contained
within a single code file, so it is easy to drop into the source tree
of a larger C or C++ program.  All the code generation and transformation
steps have already been carried out so there are no auxiliary C programs
to configure and compile and no scripts to run.  And, because the entire
library is contained in a single translation unit, compilers are able to
do more advanced optimizations resulting in a 5% to 10% performance 
improvement.  For these reasons, the amalgamation source file 
("sqlite3.c") is recommended for all applications.


The use of the amalgamation is recommended for all applications.


Building SQLite directly from individual source code files is certainly
possible, but it is not recommended.  For some specialized applications, it
might be necessary to modify the build process in ways that cannot be done
using just the prebuilt amalgamation source file downloaded from the website.
For those situations, it is recommended that a customized amalgamation be
built (as described below)
and used.  In other words, even if a project requires building SQLite 
beginning with individual source files, it is still recommended that an
amalgamation source file be used as an intermediate step.


c2: How To Compile SQLite
c3: 2. Compiling The Command-Line Interface
c5: howtocompile.html#compiling_the_command_line_interface
c4:
A build of the command-line interface requires three source
files:


sqlite3.c: The SQLite amalgamation source file
sqlite3.h: The header files that accompanies sqlite3.c and 
defines the C-language interfaces to SQLite.
shell.c: The command-line interface program itself.
This is the C source code file that contains the definition of
the main() routine and the loop that prompts for user input
and passes that input into the SQLite database engine for processing.


All three of the above source files are contained in the
amalgamation tarball available on the download page.

To build the CLI, simply put these three files in the same directory
and compile them together.  Using MSVC:


cl shell.c sqlite3.c -Fesqlite3.exe


On unix systems (or on Windows using cygwin or mingw+msys)
the command typically looks something like this:


gcc shell.c sqlite3.c -lpthread -ldl -lm -o sqlite3


The pthreads library is needed to make SQLite threadsafe.  But
since the CLI is single threaded,  we could instruct SQLite to build
in a non-threadsafe mode and thereby omit the pthreads library:


gcc -DSQLITE_THREADSAFE=0 shell.c sqlite3.c -ldl -lm -o sqlite3


The -ldl library is needed to support dynamic loading, the
sqlite3_load_extension() interface and the
load_extension() SQL function.  If these features are not required,
then they can be omitted using SQLITE_OMIT_LOAD_EXTENSION compile-time
option:


gcc -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION shell.c sqlite3.c -o sqlite3


One might want to provide other compile-time options such as
-DSQLITE_ENABLE_FTS4 or -DSQLITE_ENABLE_FTS5 for full-text search,
-DSQLITE_ENABLE_RTREE for the R*Tree search engine extension,
-DSQLITE_ENABLE_JSON1 to include JSON SQL functions, or
-DSQLITE_ENABLE_DBSTAT_VTAB for the dbstat virtual table.
In order to see extra commentary in EXPLAIN listings, add the 
-DSQLITE_ENABLE_EXPLAIN_COMMENTS option.
On unix systems, add -DHAVE_USLEEP=1 if the host machine supports the
usleep() system call.  Add -DHAVE_READLINE and the -lreadline
and -lncurses libraries to get command-line editing support.
One might also want to
specify some compiler optimization switches.  (The precompiled
CLI available for download from the SQLite website uses "-Os".)
There are countless possible variations here.  A command to
compile a full-featured shell might look something like this:


gcc -Os -I. -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_FTS4 &#92;
   -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 &#92;
   -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_EXPLAIN_COMMENTS &#92;
   -DHAVE_USLEEP -DHAVE_READLINE &#92;
   shell.c sqlite3.c -ldl -lm -lreadline -lncurses -o sqlite3


The key point is this:  Building the CLI consists of compiling 
together two C-language files.   The shell.c file contains the
definition of the entry point and the user input loop and the
SQLite amalgamation sqlite3.c contains the complete implementation
of the SQLite library.


c2: How To Compile SQLite
c3: 3. Compiling The TCL Interface
c5: howtocompile.html#compiling_the_tcl_interface
c4:
The TCL interface for SQLite is a small module that is added into
the regular amalgamation.  The result is a new amalgamated source
file called "tclsqlite3.c".  This single source file is all that
is needed to generate a shared library that can be loaded into a
standard 
tclsh or 
wish using the 
TCL load command, or to generate a
standalone tclsh that comes with SQLite built in.
A copy of the tcl amalgamation
is included on the download page as a file in the TEA tarball.

To generate a TCL-loadable library for SQLite on Linux, the following
command will suffice:


gcc -o libtclsqlite3.so -shared tclsqlite3.c -lpthread -ldl -ltcl


Building shared libraries for Mac OS X and Windows is not nearly so simple,
unfortunately.  For those platforms it is best to use the configure script
and makefile that is included with the TEA tarball.

To generate a standalone tclsh that is statically linked with SQLite,
use this compiler invocation:


gcc -DTCLSH=1 tclsqlite3.c -ltcl -lpthread -ldl -lz -lm


The trick here is the -DTCLSH=1 option.  The TCL interface module for
SQLite includes a main() procedure that initializes a TCL interpreter
and enters a command-line loop when it is compiled with -DTCLSH=1.  The
command above works on both Linux and Mac OS X, though one may need to adjust
the library options depending on the platform and which version of TCL one
is linking against.


c2: How To Compile SQLite
c3: 4. Building The Amalgamation
c5: howtocompile.html#building_the_amalgamation
c4:
The versions of the SQLite amalgamation that are supplied on the
download page are normally adequate for most users.  However, some
projects may want or need to build their own amalgamations.  A common
reason for building a custom amalgamation is in order to use certain
compile-time options to customize the SQLite library.  Recall that
the SQLite amalgamation contains a lot of C-code that is generated by
auxiliary programs and scripts.  Many of the compile-time
options effect this generated code and must be supplied to the code
generators before the amalgamation is assembled.  The set of 
compile-time options that must be passed into the code generators can
vary from one release of SQLite to the next, but at the time of this
writing (circa SQLite 3.6.20, 2009-11-04) the set of options that must
be known by the code generators includes:


SQLITE_ENABLE_UPDATE_DELETE_LIMIT
SQLITE_OMIT_ALTERTABLE
SQLITE_OMIT_ANALYZE
SQLITE_OMIT_ATTACH
SQLITE_OMIT_AUTOINCREMENT
SQLITE_OMIT_CAST
SQLITE_OMIT_COMPOUND_SELECT
SQLITE_OMIT_EXPLAIN
SQLITE_OMIT_FOREIGN_KEY
SQLITE_OMIT_PRAGMA
SQLITE_OMIT_REINDEX
SQLITE_OMIT_SUBQUERY
SQLITE_OMIT_TEMPDB
SQLITE_OMIT_TRIGGER
SQLITE_OMIT_VACUUM
SQLITE_OMIT_VIEW
SQLITE_OMIT_VIRTUALTABLE


To build a custom amalgamation, first download the original individual
source files onto a unix or unix-like development platform.  
Be sure to get the original source
files not the "preprocessed source files".  One can obtain the complete
set of original source files either from the download page or directly
from the configuration management system.

Suppose the SQLite source tree is stored in a directory named "sqlite".
Plan to construct the amalgamation in a parallel directory named (for
example) "bld".  First construct an appropriate Makefile by either
running the configure script at the top of the SQLite source tree, or by
making a copy of one of the template Makefiles at the top of the source tree.
Then hand edit this Makefile to include the desired compile-time options.
Finally run:


make sqlite3.c


Or on Windows with MSVC:


nmake /f Makefile.msc sqlite3.c


The "sqlite3.c" make target will automatically construct the regular
"sqlite3.c" amalgamation source file, its header file
"sqlite3.h", and the "tclsqlite3.c" amalgamation source
file that includes the TCL interface.
Afterwards, the needed files can be copied into project directories and
compiled according to the procedures outlined above.


c2: How To Compile SQLite
c3: 5. Building A Windows DLL
c5: howtocompile.html#building_a_windows_dll
c4:
To build a DLL of SQLite for use in Windows, first acquire the
appropriate amalgamated source code files, sqlite3.c and sqlite3.h.  
These can either
be downloaded from the SQLite website
or custom generated from sources as shown above.

With source code files in the working directory, a DLL
can be generated using MSVC with the following command:


cl sqlite3.c -link -dll -out:sqlite3.dll


The above command should be run from the MSVC Native Tools Command
Prompt.  If you have MSVC installed on your machine, you probably
have multiple versions of this Command Prompt, for native builds
for x86 and x64, and possibly also for cross-compiling to ARM.
Use the appropriate Command Prompt depending on the desired DLL.

If using the MinGW compiler, the command-line is this:


gcc -shared sqlite3.c -o sqlite3.dll


Note that MinGW generates 32-bit DLLs only.  There is a separate
MinGW64 project that can be used to generate 64-bit DLLs.  Presumably
the command-line syntax is similar.
Also note that recent versions of MSVC generate DLLs that will not work
on WinXP and earlier versions of Windows.  So for maximum compatibility
of your generated DLL, MinGW is recommended.  A good rule-of-thumb
is to generate 32-bit DLLs using MinGW and 64-bit DLLs using MSVC.

In most cases, you will want to supplement the basic commands above with
compile-time options appropriate for your application.  Commonly used
compile-time options include:


-Os - Optimize for size. 
Make the DLL as small as possible.

-O2 - Optimize for speed.  This will make the DLL larger by
unrolling loops and inlining functions.

-DSQLITE_ENABLE_FTS4 -
Include the full-text search engine code in SQLite.

-DSQLITE_ENABLE_RTREE - Include the R-Tree extension.

-DSQLITE_ENABLE_COLUMN_METADATA -
This enables some extra APIs that are required by some common systems,
including Ruby-on-Rails.

This page last modified on  2021-10-12 03:48:52 UTC


c2: Temporary Files Used By SQLite
c3: 1. Introduction
c5: tempfiles.html#introduction
c4:
One of the distinctive features of
SQLite is that a database consists of a single disk file.
This simplifies the use of SQLite since moving or backing up a
database is a simple as copying a single file.  It also makes
SQLite appropriate for use as an
application file format.
But while a complete database is held in a single disk file,
SQLite does make use of many temporary files during the
course of processing a database.



This article describes the various temporary files that SQLite
creates and uses.  It describes when the files are created, when
they are deleted, what they are used for, why they are important,
and how to avoid them on systems where creating temporary files is
expensive.



The manner in which SQLite uses temporary files is not considered
part of the contract that SQLite makes with applications.  The
information in this document is a correct description of how
SQLite operates at the time that this document was written or last
updated.  But there is no guarantee that future versions of SQLite
will use temporary files in the same way.  New kinds of temporary
files might be employed  and some of
the current temporary file uses might be discontinued
in future releases of SQLite.


c2: Temporary Files Used By SQLite
c3: 2. Nine Kinds Of Temporary Files
c5: tempfiles.html#nine_kinds_of_temporary_files
c4:
SQLite currently uses nine distinct types of temporary files:



Rollback journals
Super-journals
Write-ahead Log (WAL) files
Shared-memory files
Statement journals
TEMP databases
Materializations of views and subqueries
Transient indices
Transient databases used by VACUUM



Additional information about each of these temporary file types
is in the sequel.


c2: Temporary Files Used By SQLite
c3: 2.1. Rollback Journals
c5: tempfiles.html#rollback_journals
c4:
A rollback journal is a temporary file used to implement
atomic commit and rollback capabilities in SQLite.
(For a detailed discussion of how this works, see
the separate document titled
Atomic Commit In SQLite.)
The rollback journal is always located in the same directory
as the database file and has the same name as the database
file except with the 8 characters "-journal" appended.
The rollback journal is usually created when a transaction
is first started and is usually deleted when a transaction
commits or rolls back.
The rollback journal file is essential for implementing the
atomic commit and rollback capabilities of SQLite.  Without
a rollback journal, SQLite would be unable to rollback an
incomplete transaction, and if a crash or power loss occurred
in the middle of a transaction the entire database would likely
go corrupt without a rollback journal.



The rollback journal is usually created and destroyed at the
start and end of a transaction, respectively.  But there are exceptions
to this rule.



If a crash or power loss occurs in the middle of a transaction,
then the rollback journal file is left on disk.  The next time
another application attempts to open the database file, it notices
the presence of the abandoned rollback journal (we call it a "hot
journal" in this circumstance) and uses the information in the
journal to restore the database to its state prior to the start
of the incomplete transaction.  This is how SQLite implements
atomic commit.



If an application puts SQLite in 
exclusive locking mode using
the pragma:



PRAGMA locking_mode=EXCLUSIVE;



SQLite creates a new rollback journal at the start of the first
transaction within an exclusive locking mode session.  But at the
conclusion of the transaction, it does not delete the rollback
journal.  The rollback journal might be truncated, or its header
might be zeroed (depending on what version of SQLite you are using)
but the rollback journal is not deleted.  The rollback journal is
not deleted until exclusive access mode is exited.


Rollback journal creation and deletion is also changed by the
journal_mode pragma.
The default journaling mode is DELETE, which is the default behavior
of deleting the rollback journal file at the end of each transaction,
as described above.  The PERSIST journal mode foregoes the deletion of
the journal file and instead overwrites the rollback journal header
with zeros, which prevents other processes from rolling back the
journal and thus has the same effect as deleting the journal file, though
without the expense of actually removing the file from disk.  In other
words, journal mode PERSIST exhibits the same behavior as is seen
in EXCLUSIVE locking mode. The
OFF journal mode causes SQLite to omit the rollback journal, completely.
In other words, no rollback journal is ever written if journal mode is
set to OFF.
The OFF journal mode disables the atomic
commit and rollback capabilities of SQLite.  The ROLLBACK command
is not available when OFF journal mode is set.  And if a crash or power
loss occurs in the middle of a transaction that uses the OFF journal
mode, no recovery is possible and the database file will likely
go corrupt.
The MEMORY journal mode causes the rollback journal to be stored in
memory rather than on disk.  The ROLLBACK command still works when
the journal mode is MEMORY, but because no file exists on disks for
recovery, a crash or power loss in the middle of a transaction that uses
the MEMORY journal mode will likely result in a corrupt database.


c2: Temporary Files Used By SQLite
c3: 2.2. Write-Ahead Log (WAL) Files
c5: tempfiles.html#write_ahead_log_wal_files
c4:
A write-ahead log or WAL file is used in place of a rollback journal
when SQLite is operating in WAL mode.  As with the rollback journal,
the purpose of the WAL file is to implement atomic commit and rollback.
The WAL file is always located in the same directory
as the database file and has the same name as the database
file except with the 4 characters "-wal" appended.
The WAL file is created when the first connection to the
database is opened and is normally removed when the last
connection to the database closes.  However, if the last connection
does not shutdown cleanly, the WAL file will remain in the filesystem
and will be automatically cleaned up the next time the database is
opened.


c2: Temporary Files Used By SQLite
c3: 2.3. Shared-Memory Files
c5: tempfiles.html#shared_memory_files
c4:
When operating in WAL mode, all SQLite database connections associated
with the same database file need to share some memory that is used as an
index for the WAL file.  In most implementations, this shared memory is
implemented by calling mmap() on a file created for this sole purpose:
the shared-memory file.  The shared-memory file, if it exists, is located
in the same directory as the database file and has the same name as the
database file except with the 4 characters "-shm" appended.
Shared memory files only exist while running in WAL mode.



The shared-memory file contains no persistent content.  The only purpose
of the shared-memory file is to provide a block of shared memory for use
by multiple processes all accessing the same database in WAL mode.
If the VFS is able to provide an alternative method for accessing shared
memory, then that alternative method might be used rather than the
shared-memory file.  For example, if PRAGMA locking_mode is set to
EXCLUSIVE (meaning that only one process is able to access the database
file) then the shared memory will be allocated from heap rather than out
of the shared-memory file, and the shared-memory file will never be
created.



The shared-memory file has the same lifetime as its associated WAL file.
The shared-memory file is created when the WAL file is created and is
deleted when the WAL file is deleted.  During WAL file recovery, the
shared memory file is recreated from scratch based on the contents of
the WAL file being recovered.


c2: Temporary Files Used By SQLite
c3: 2.4. Super-Journal Files
c5: tempfiles.html#super_journal_files
c4:
The super-journal file is used as part of the atomic commit
process when a single transaction makes changes to multiple
databases that have been added to a single database connection
using the ATTACH statement.  The super-journal file is always
located in the same directory as the main database file
(the main database file is the database that is identified
in the original sqlite3_open(), sqlite3_open16(), or
sqlite3_open_v2() call that created the database connection)
with a randomized suffix.  The super-journal file contains
the names of all of the various attached auxiliary databases
that were changed during the transaction.  The multi-database
transaction commits when the super-journal file is deleted.
See the documentation titled
Atomic Commit In SQLite for
additional detail.



Without the super-journal, the transaction commit on a multi-database
transaction would be atomic for each database individually, but it
would not be atomic across all databases.  In other words, if the
commit were interrupted in the middle by a crash or power loss, then
the changes to one of the databases might complete while the changes
to another database might roll back.  The super-journal causes all
changes in all databases to either rollback or commit together.



The super-journal file is only created for COMMIT operations that
involve multiple database files where at least two of the databases 
meet all of the following requirements:


The database is modified by the transaction
The PRAGMA synchronous setting is not OFF
The PRAGMA journal_mode is not OFF, MEMORY, or WAL



This means that SQLite transactions are not atomic
across multiple database files on a power-loss when the database 
files have synchronous turned off or when they are using journal 
modes of OFF, MEMORY, or WAL.  For synchronous OFF and for
journal_modes OFF and MEMORY, database will usually corrupt if
a transaction commit is interrupted by a power loss.  For 
WAL mode, individual database files are updated atomically
across a power-loss, but in the case of a multi-file transactions,
some files might rollback while others roll forward after
power is restored.


c2: Temporary Files Used By SQLite
c3: 2.5. Statement Journal Files
c5: tempfiles.html#statement_journal_files
c4:
A statement journal file is used to rollback partial results of
a single statement within a larger transaction.  For example, suppose
an UPDATE statement will attempt to modify 100 rows in the database.
But after modifying the first 50 rows, the UPDATE hits
a constraint violation which should block the entire statement.
The statement journal is used to undo the first 50 row changes
so that the database is restored to the state it was in at the start
of the statement.



A statement journal is only created for an UPDATE or INSERT statement
that might change multiple rows of a database and which might hit a
constraint or a RAISE exception within a trigger and thus need to
undo partial results.
If the UPDATE or INSERT is not contained within BEGIN...COMMIT and if
there are no other active statements on the same database connection then
no statement journal is created since the ordinary
rollback journal can be used instead.
The statement journal is also omitted if an alternative
conflict resolution algorithm is
used.  For example:



UPDATE OR FAIL ...
UPDATE OR IGNORE ...
UPDATE OR REPLACE ...
UPDATE OR ROLLBACK ...
INSERT OR FAIL ...
INSERT OR IGNORE ...
INSERT OR REPLACE ...
INSERT OR ROLLBACK ...
REPLACE INTO ....



The statement journal is given a randomized name, not necessarily
in the same directory as the main database, and is automatically
deleted at the conclusion of the transaction.  The size of the
statement journal is proportional to the size of the change implemented
by the UPDATE or INSERT statement that caused the statement journal
to be created.


c2: Temporary Files Used By SQLite
c3: 2.6. TEMP Databases
c5: tempfiles.html#temp_databases
c4:
Tables created using the "CREATE TEMP TABLE" syntax are only
visible to the database connection in which the "CREATE TEMP TABLE"
statement is originally evaluated.  These TEMP tables, together
with any associated indices, triggers, and views, are collectively
stored in a separate temporary database file that is created as
soon as the first "CREATE TEMP TABLE" statement is seen.
This separate temporary database file also has an associated
rollback journal.
The temporary database file used to store TEMP tables is deleted
automatically when the database connection is closed
using sqlite3_close().



The TEMP database file is very similar to auxiliary database
files added using the ATTACH statement, though with a few
special properties.
The TEMP database is always automatically deleted when the
database connection is closed.
The TEMP database always uses the
synchronous=OFF and journal_mode=PERSIST
PRAGMA settings.
And, the TEMP database cannot be used with DETACH nor can
another process ATTACH the TEMP database.



The temporary files associated with the TEMP database and its
rollback journal are only created if the application makes use
of the "CREATE TEMP TABLE" statement.


c2: Temporary Files Used By SQLite
c3: 2.7. Materializations Of Views And Subqueries
c5: tempfiles.html#materializations_of_views_and_subqueries
c4:
Queries that contain subqueries must sometime evaluate
the subqueries separately and store the results in a temporary
table, then use the content of the temporary table to evaluate
the outer query.
We call this "materializing" the subquery.
The query optimizer in SQLite attempts to avoid materializing,
but sometimes it is not easily avoidable.
The temporary tables created by materialization are each stored
in their own separate temporary file, which is automatically
deleted at the conclusion of the query.
The size of these temporary tables depends on the amount of
data in the materialization of the subquery, of course.



A subquery on the right-hand side of IN operator must often
be materialized.  For example:



SELECT * FROM ex1 WHERE ex1.a IN (SELECT b FROM ex2);



In the query above, the subquery "SELECT b FROM ex2" is evaluated
and its results are stored in a temporary table (actually a temporary
index) that allows one to determine whether or not a value ex2.b
exists using a simple binary search.  Once this table is constructed,
the outer query is run and for each prospective result row a check
is made to see if ex1.a is contained within the temporary table.
The row is output only if the check is true.



To avoid creating the temporary table, the query might be rewritten
as follows:



SELECT * FROM ex1 WHERE EXISTS(SELECT 1 FROM ex2 WHERE ex2.b=ex1.a);



Recent versions of SQLite (version 3.5.4 2007-12-14) and later)
will do this rewrite automatically
if an index exists on the column ex2.b.



If the right-hand side of an IN operator can be list of values
as in the following:


SELECT * FROM ex1 WHERE a IN (1,2,3);


List values on the right-hand side of IN are treated as a 
subquery that must be materialized.  In other words, the
previous statement acts as if it were:


SELECT * FROM ex1 WHERE a IN (SELECT 1 UNION ALL
                              SELECT 2 UNION ALL
                              SELECT 3);


A temporary index is always used to hold the values of the
right-hand side of an IN operator when that right-hand side
is a list of values.



Subqueries might also need to be materialized when they appear
in the FROM clause of a SELECT statement.  For example:



SELECT * FROM ex1 JOIN (SELECT b FROM ex2) AS t ON t.b=ex1.a;



Depending on the query, SQLite might need to materialize the 
"(SELECT b FROM ex2)" subquery into a temporary table, then
perform the join between ex1 and the temporary table.  The
query optimizer tries to avoid this by "flattening" the
query.  In the previous example the query can be flattened,
and SQLite will automatically transform the query into



SELECT ex1.*, ex2.b FROM ex1 JOIN ex2 ON ex2.b=ex1.a;



More complex queries may or may not be able to employ query
flattening to avoid the temporary table.  Whether or not
the query can be flattened depends on such factors as whether
or not the subquery or outer query contain aggregate functions,
ORDER BY or GROUP BY clauses, LIMIT clauses, and so forth.
The rules for when a query can and cannot be flattened are
very complex and are beyond the scope of this document.


c2: Temporary Files Used By SQLite
c3: 2.8. Transient Indices
c5: tempfiles.html#transient_indices
c4:
SQLite may make use of transient indices to
implement SQL language features such as:



An ORDER BY or GROUP BY clause
The DISTINCT keyword in an aggregate query
Compound SELECT statements joined by UNION, EXCEPT, or INTERSECT



Each transient index is stored in its own temporary file.
The temporary file for a transient index is automatically deleted
at the end of the statement that uses it.



SQLite strives to implement ORDER BY clauses using a preexisting
index.  If an appropriate index already exists, SQLite will walk
the index, rather than the underlying table, to extract the 
requested information, and thus cause the rows to come out in
the desired order.  But if SQLite cannot find an appropriate index
it will evaluate the query and store each row in a transient index
whose data is the row data and whose key is the ORDER BY terms.
After the query is evaluated, SQLite goes back and walks the
transient index from beginning to end in order to output the
rows in the desired order.



SQLite implements GROUP BY by ordering the output rows in the
order suggested by the GROUP BY terms.  Each output row is
compared to the previous to see if it starts a new "group".
The ordering by GROUP BY terms is done in exactly the same way
as the ordering by ORDER BY terms.  A preexisting index is used
if possible, but if no suitable index is available, a transient
index is created.



The DISTINCT keyword on an aggregate query is implemented by
creating a transient index in a temporary file and storing
each result row in that index.  As new result rows are computed
a check is made to see if they already exist in the transient
index and if they do the new result row is discarded.



The UNION operator for compound queries is implemented by creating
a transient index in a temporary file and storing the results
of the left and right subquery in the transient index, discarding
duplicates.  After both subqueries have been evaluated, the
transient index is walked from beginning to end to generate the final output.



The EXCEPT operator for compound queries is implemented by creating
a transient index in a temporary file, storing the results of the
left subquery in this transient index, then removing the result 
from right subquery from the transient index, and finally walking
the index from beginning to end to obtain the final output.



The INTERSECT operator for compound queries is implemented by
creating two separate transient indices, each in a separate
temporary file.  The left and right subqueries are evaluated
each into a separate transient index.  Then the two indices
are walked together and entries that appear in both indices
are output.



Note that the UNION ALL operator for compound queries does not
use transient indices by itself (though of course the right
and left subqueries of the UNION ALL might use transient indices
depending on how they are composed.)


c2: Temporary Files Used By SQLite
c3: 2.9. Transient Database Used By VACUUM
c5: tempfiles.html#transient_database_used_by_vacuum_
c4:
The VACUUM command works by creating a temporary file
and then rebuilding the entire database into that temporary
file.  Then the content of the temporary file is copied back
into the original database file and the temporary file is
deleted.



The temporary file created by the VACUUM command exists only
for the duration of the command itself.  The size of the temporary
file will be no larger than the original database.


c2: Temporary Files Used By SQLite
c3: 3. The SQLITE_TEMP_STORE Compile-Time Parameter and Pragma
c5: tempfiles.html#the_sqlite_temp_store_compile_time_parameter_and_pragma
c4:
The temporary files associated with transaction control, namely
the rollback journal, super-journal, write-ahead log (WAL) files,
and shared-memory files, are always written to disk.
But the other kinds of temporary files might be stored in memory
only and never written to disk.
Whether or not temporary files other than the rollback,
super, and statement journals are written to disk or stored only in memory
depends on the SQLITE_TEMP_STORE compile-time parameter, the
temp_store pragma,
and on the size of the temporary file.



The SQLITE_TEMP_STORE compile-time parameter is a #define whose value is
an integer between 0 and 3, inclusive.  The meaning of the
SQLITE_TEMP_STORE compile-time parameter is as follows:




Temporary files are always stored on disk regardless of the setting
of the temp_store pragma.


Temporary files are stored on disk by default but this can be
overridden by the temp_store pragma.


Temporary files are stored in memory by default but this can be
overridden by the temp_store pragma.


Temporary files are always stored in memory regardless of the setting
of the temp_store pragma.




The default value of the SQLITE_TEMP_STORE compile-time parameter is 1,
which means to store temporary files on disk but provide the option
of overriding the behavior using the temp_store pragma.



The temp_store pragma has
an integer value which also influences the decision of where to store
temporary files.  The values of the temp_store pragma have the
following meanings:




Use either disk or memory storage for temporary files as determined
by the SQLITE_TEMP_STORE compile-time parameter.


If the SQLITE_TEMP_STORE compile-time parameter specifies memory storage for
temporary files, then override that decision and use disk storage instead.
Otherwise follow the recommendation of the SQLITE_TEMP_STORE compile-time
parameter.


If the SQLITE_TEMP_STORE compile-time parameter specifies disk storage for
temporary files, then override that decision and use memory storage instead.
Otherwise follow the recommendation of the SQLITE_TEMP_STORE compile-time
parameter.




The default setting for the temp_store pragma is 0,
which means to following the recommendation of SQLITE_TEMP_STORE compile-time
parameter.



To reiterate, the SQLITE_TEMP_STORE compile-time parameter and the 
temp_store pragma only
influence the temporary files other than the rollback journal
and the super-journal.  The rollback journal and the
super-journal are always written to disk regardless of the settings of
the SQLITE_TEMP_STORE compile-time parameter and the
temp_store pragma.


c2: Temporary Files Used By SQLite
c3: 4. Other Temporary File Optimizations
c5: tempfiles.html#other_temporary_file_optimizations
c4:
SQLite uses a page cache of recently read and written database
pages.  This page cache is used not just for the main database
file but also for transient indices and tables stored in temporary
files.  If SQLite needs to use a temporary index or table and
the SQLITE_TEMP_STORE compile-time parameter and the
temp_store pragma are
set to store temporary tables and index on disk, the information
is still initially stored in memory in the page cache.  The 
temporary file is not opened and the information is not truly
written to disk until the page cache is full.



This means that for many common cases where the temporary tables
and indices are small (small enough to fit into the page cache)
no temporary files are created and no disk I/O occurs.  Only
when the temporary data becomes too large to fit in RAM does
the information spill to disk.



Each temporary table and index is given its own page cache
which can store a maximum number of database pages determined
by the SQLITE_DEFAULT_TEMP_CACHE_SIZE compile-time parameter.
(The default value is 500 pages.)
The maximum number of database pages in the page cache is the
same for every temporary table and index.  The value cannot
be changed at run-time or on a per-table or per-index basis.
Each temporary file gets its own private page cache with its
own SQLITE_DEFAULT_TEMP_CACHE_SIZE page limit.


c2: Temporary Files Used By SQLite
c3: 5. Temporary File Storage Locations
c5: tempfiles.html#temporary_file_storage_locations
c4:
The directory or folder in which temporary files are created is
determined by the OS-specific VFS.


On unix-like systems, directories are searched in the following order:

The directory set by PRAGMA temp_store_directory or by the
    sqlite3_temp_directory global variable
The SQLITE_TMPDIR environment variable
The TMPDIR environment variable
/var/tmp
/usr/tmp
/tmp
The current working directory (".")

The first of the above that is found to exist and have the write and
execute bits set is used.  The final "." fallback is important for some
applications that use SQLite inside of chroot jails that do not have
the standard temporary file locations available.


On Windows systems, folders are searched in the following order:

The folder set by PRAGMA temp_store_directory or by the
    sqlite3_temp_directory global variable
The folder returned by the GetTempPath() system interface.

SQLite itself does not pay any attention to environment variables
in this case, though presumably the GetTempPath() system call does.
The search algorithm is different for CYGWIN builds.  Check the 
source code for details.
This page last modified on  2020-08-16 11:16:26 UTC


c2: The SQLite OS Interface or "VFS"
c3: 1. Introduction
c5: vfs.html#introduction
c4:
This article describes the SQLite OS portability layer or "VFS" - the
module at the bottom of the SQLite implementation stack
that provides portability across operating systems.


c2: The SQLite OS Interface or "VFS"
c3: 2. The VFS In Relation To The Rest Of SQLite
c5: vfs.html#the_vfs_in_relation_to_the_rest_of_sqlite
c4:
The internal organization of the SQLite library can be viewed as the
stack of modules shown to the right.
The Tokenizer, Parser, and Code Generator components are used to
process SQL statements and convert them into executable programs 
in a virtual machine language or byte code.
Roughly speaking, these top three layers implement
sqlite3_prepare_v2().  The byte code generated by the top three
layers is a prepared statement.
The Virtual Machine module is responsible for running the SQL statement 
byte code. The B-Tree module organizes a database file into multiple 
key/value stores with ordered keys and logarithmic performance. 
The Pager module is responsible for loading pages of the database
file into memory, for implementing and controlling transactions, and 
for creating and maintaining the journal files that prevent database 
corruption following a crash or power failure. 
The OS Interface is a thin abstraction that provides a common set of 
routines for adapting SQLite to run on different operating systems.
Roughly speaking, the bottom four layers implement
sqlite3_step().



This article is about the bottom layer.


The OS Interface - also called the "VFS" - is what makes SQLite 
portable across operating systems.  Whenever any of the other modules
in SQLite needs to communicate with the operating
system, they invoke methods in the VFS.  The VFS then invokes the
operating-specific code needed to satisfy the request.
Hence, porting SQLite to a new
operating system is simply a matter of writing a new OS interface layer
or "VFS".


c2: The SQLite OS Interface or "VFS"
c3: 3. Multiple VFSes
c5: vfs.html#multiple_vfses
c4:
The standard SQLite source tree contains built-in VFSes for unix
and windows.  Alternative VFSes can be
added at start-time or run-time using the
sqlite3_vfs_register() interface.



Multiple VFSes can be registered at the same time.
Each VFS has a unique names.
Separate database connections within the same process can be using
different VFSes at the same time.   For that matter, if a single
database connection has multiple database files open using
the ATTACH command, then each attached database might be using a
different VFS.


c2: The SQLite OS Interface or "VFS"
c3: 3.1. Standard Unix VFSes
c5: vfs.html#standard_unix_vfses
c4:
Unix builds come with multiple built-in VFSes.  The default VFS
for unix is called "unix" and is used in most applications.
Other VFSes that might be found in unix (depending on compile-time
options) include:



unix-dotfile - uses dot-file locking rather than
          POSIX advisory locks.
unix-excl - obtains and holds an exclusive lock on
          database files, preventing other processes from accessing the
          database.  Also keeps the wal-index in heap rather than in
          shared memory.
unix-none - all file locking operations are no-ops.
unix-namedsem - uses named semaphores for file locking.
       VXWorks only.



The various unix VFSes differ only in the way they handle file locking -
they share most of their implementation in common with one another and
are all located in the same SQLite source file:  
os_unix.c.
Note that except for "unix" and "unix-excl", the various unix VFSes all
use incompatible locking implementations.  If two processes are accessing
the same SQLite database using different unix VFSes, they may
not see each others locks and may end up interfering with one another,
resulting in database corruption.  The "unix-none" VFS in particular
does no locking at all and will easily result in database corruption if
used by two or more database connections at the same time.
Programmers are encouraged to use only "unix" or "unix-excl" unless
there is a compelling reason to do otherwise.


c2: The SQLite OS Interface or "VFS"
c3: 3.2. Standard Windows VFSes
c5: vfs.html#standard_windows_vfses
c4:
Windows builds also come with multiple built-in VFSes.  The default
Windows VFS is called "win32" and is used in most applications.
Other VFSes that might be found on windows builds include:



win32-longpath - like "win32" except that pathnames can
          be up to 65534 bytes in length, whereas pathnames max out at
          1040 bytes in "win32".
win32-none - all file locking operations are no-ops.
win32-longpath-none - combination of "win32-longpath"
          and "win32-none" - long pathnames are supported and all lock
          operations are no-ops.


As with unix, most of the code for the various Windows VFSes is shared.


c2: The SQLite OS Interface or "VFS"
c3: 3.3. Specifying Which VFS To Use
c5: vfs.html#specifying_which_vfs_to_use
c4:
There is always one VFS which is the default VFS.  On unix systems,
the "unix" VFS comes up as the default and on windows it is "win32".
If no other actions are taken, new database connections will make use
of the default VFS.



The default VFS can be changed by registering or re-registering the
VFS using the sqlite3_vfs_register() interface with a second parameter
of 1.  Hence, if a (unix) process wants to always use the "unix-nolock" VFS 
in place of "unix", the following code would work:



sqlite3_vfs_register(sqlite3_vfs_find("unix-nolock"), 1);



An alternate VFS can also be specified as the 4th parameter to the
sqlite3_open_v2() function.  For example:



int rc = sqlite3_open_v2("demo.db", &db, SQLITE_OPEN_READWRITE, "unix-nolock");



Finally, if URI filenames have been enabled, then the alternative
VFS can be specified using the "vfs=" parameter on the URI.  This technique
works with sqlite3_open(), sqlite3_open16(), sqlite3_open_v2(), and
when a new database is ATTACH-ed to an existing database connection.
For example:



ATTACH 'file:demo2.db?vfs=unix-none' AS demo2;



The VFS specified by a URI has the highest priority.  After that comes
a VFS specified as the fourth argument to sqlite3_open_v2().  The
default VFS is used if no VFS is specified otherwise.


c2: The SQLite OS Interface or "VFS"
c3: 3.4. VFS Shims
c5: vfs.html#vfs_shims
c4:
From the point of view of the uppers layers of the SQLite stack, each
open database file uses exactly one VFS.
But in practice, a particular VFS might
just be a thin wrapper around another VFS that does the real work.
We call a wrapper VFS a "shim".



A simple example of a shim is the "vfstrace" VFS.  This is a VFS
(implemented in the 
test_vfstrace.c
source file) that writes a message associated with each VFS method call
into a log file, then passes control off to another VFS to do the actual
work.


c2: The SQLite OS Interface or "VFS"
c3: 3.5. Other Example VFSes
c5: vfs.html#other_example_vfses
c4:
The following are other VFS implementations available in the public
SQLite source tree:




appendvfs.c -
This VFS allows an SQLite database to be appended to the end of some
other file.  This can be used, for example, to append an SQLite database
onto the end of an executable such that, when run, it can easily
locate the appended database. The command-line shell will use this
VFS if launched with the --append option, and its .archive command
will use it given the --append flag.


test_demovfs.c - 
This file implements a very simple VFS named "demo" that uses POSIX 
functions such as
open(), read(), write(), fsync(), close(), fsync(), sleep(), time(),
and so forth.  This VFS only works on unix systems.  But it is not
intended as a replacement for the standard "unix" VFS used by default
on unix platforms.  The "demo" VFS is deliberately kept very simple
so that it can be used as a learning aid or as template for building
other VFSes or for porting SQLite to new operating systems.


test_quota.c - 
This file implements a shim called "quota" that enforces cumulative
file size limits on a collection of database files.  An auxiliary
interface is used to define "quota groups".  A quota group is a
set of files (database files, journals, and temporary files) whose
names all match a GLOB pattern.  The sum of the sizes of all files
in each quota group is tracked, and if that sum exceeds a threshold
defined for the quota group, a callback function is invoked.  That
callback can either increase the threshold or cause the operation
that would have exceeded the quota to fail with an 
SQLITE_FULL error.  One of the uses of this shim is used to enforce 
resource limits on application databases in Firefox.


test_multiplex.c - 
This file implements a shim that allows database files to exceed the
maximum file size of the underlying filesystem.  This shim presents
an interface to the upper six layers of SQLite that makes it look like
very large files are being used, when in reality each such large file
is split up into many smaller files on the underlying system.
This shim has been used, for example, to allow databases to grow
larger than 2 gibibytes on FAT16 filesystems.


test_onefile.c - 
This file implements a demonstration VFS named "fs" that shows how SQLite 
can be used on an embedded device that lacks a filesystem.  Content is
written directly to the underlying media.  A VFS derived from this
demonstration code could be used by a gadget with a limited amount of
flash memory to make SQLite behave as the filesystem for the flash memory
on the device.


test_journal.c - 
This file implements a shim used during SQLite testing that verifies that
the database and rollback journal are written in the correct order and
are "synced" at appropriate times in order to guarantee that the database
can recover from a power lose are hard reset at any time.  The shim
checks several invariants on the operation of databases and rollback
journals and raises exceptions if any of those invariants are violated.
These invariants, in turn, assure that the database is always recoverable.
Running a large suite of test cases using this shim provides added
assurance that SQLite databases will not be damaged by unexpected
power failures or device resets.


test_vfs.c - 
This file implements a shim that can be used to simulate filesystem faults.
This shim is used during testing to verify that SQLite responses sanely
to hardware malfunctions or to other error conditions such as running out
of filesystem space that are difficult to test on a real system.



There are other VFS implementations both in the core SQLite source code
library and in available extensions.  The list above is not meant to be
exhaustive but merely representative of the kinds of features that can
be realized using the VFS interface.


c2: The SQLite OS Interface or "VFS"
c3: 4. VFS Implementations
c5: vfs.html#vfs_implementations
c4:
A new VFS is implemented by subclassing three objects:



sqlite3_vfs
sqlite3_io_methods
sqlite3_file



An sqlite3_vfs object defines the name of the VFS and the core
methods that implement the interface to the operating system, such
as checking for existence of files, deleting files, creating files
and opening and for reading and/or writing, converting filenames
into their canonical form.  The sqlite3_vfs object also contains
methods for obtaining randomness from the operating system, for
suspending a process (sleeping) and for finding the current date and
time.



The sqlite3_file object represents an open file.
The xOpen method of sqlite3_vfs constructs an sqlite3_file
object when the file is opened.  The sqlite3_file keeps track
of the state of the file while it is opened.



The sqlite3_io_methods object holds the methods used to interact
with an open file.  Each sqlite3_file contains a pointer to 
an sqlite3_io_methods object that is appropriate for the file it
represents.  The sqlite3_io_methods object contains methods to do
things such as read and write from the file, to truncate the file,
to flush any changes to persistent storage, to find the size of the
file, to lock and unlock the file, and to close file and destroy
the sqlite3_file object.



Writing the code for a new VFS involves constructing a subclass for
the sqlite3_vfs object and then registering that VFS object using
a call to sqlite3_vfs_register().  The VFS implementation also
provides subclasses for sqlite3_file and sqlite3_io_methods but
those objects are not registered directly with SQLite.  Instead, the
sqlite3_file object is returned from the xOpen method of
sqlite3_vfs and the sqlite3_file object points to an instance
of the sqlite3_io_methods object.

This page last modified on  2021-12-06 01:48:47 UTC


c2: The Use Of assert() In SQLite
c3: 1. Assert() And Similar Macros In SQLite
c5: assert.html#assert_and_similar_macros_in_sqlite
c4:
The assert(X) macro is 
part of standard C, in the
&lt;assert.h&gt; header file.
SQLite adds three other assert()-like macros named NEVER(X), ALWAYS(X),
and testcase(X).


assert(X) &rarr;
The assert(X) statement indicates that the condition X is always true.
In other words, X is an invariant.  The assert(X) macro works like a
procedure in that it has no return value.

ALWAYS(X) &rarr;
The ALWAYS(X) function indicates that condition X is always true as far
as the developers know, but there is no proof the X is true, or the
proof is complex and error-prone, or the proof depends on implementation
details that are likely to change in the future.  ALWAYS(X) behaves like
a function that returns the boolean value X, and is intended to be used
within the conditional of an "if" statement.

NEVER(X) &rarr;
The NEVER(X) function indicates that condition X is never true.  This
is the negative analog of the ALWAYS(X) function.

testcase(X) &rarr;
The testcase(X) statement indicates that X is sometimes true and sometimes
false.  In other words, testcase(X) indicates that X is definitely not an
invariant.  Since SQLite uses 100% MC/DC testing, the presence of a
testcase(X) macro indicates that not only is it possible for X to be either
true or false, but there are test cases to demonstrate this.



SQLite version 3.22.0 (2018-01-22) contains 5290 assert() macros,
839 testcase() macros, 88 ALWAYS() macros, and 63 NEVER() macros.


c2: The Use Of assert() In SQLite
c3: 1.1. Philosophy of assert()
c5: assert.html#philosophy_of_assert_
c4:
In SQLite, the presence of assert(X) means that the developers have
a proof that X is always true.  Readers can depend upon X being true to
help them reason about the code.  An assert(X) is a strong statement
about the truth of X.  There is no doubt.

The ALWAYS(X) and NEVER(X) macros are a weaker statement about the
truth of X.  The presence of ALWAYS(X) or NEVER(X) means that the developers
believe X is always or never true, but there is no proof, or the proof
is complex and error-prone, or the proof depends on other aspects 
of the system that seem likely to change.

Other systems sometimes use assert(X) in a way that is
similar to the use of ALWAYS(X) or NEVER(X) in SQLite.
Developers will add an assert(X) as a 
tacit acknowledgement that they
do not fully believe that X is always true.
We believe that this use of assert(X) is wrong and violates the intent
and purpose of having assert(X) available in C in the first place.
An assert(X) should not be seen as a safety-net or top-rope used to
guard against mistakes.  Nor is assert(X) appropriate for defense-in-depth.
An ALWAYS(X) or NEVER(X) macro, or something similar, should be used in 
those cases because ALWAYS(X) or NEVER(X) will be followed by code to
actually deal with the problem when the programmers reasoning
turns out to be wrong.  Since the code that follows ALWAYS(X) or NEVER(X)
is untested, it should be something very simple, like a "return" statement,
that is easily verified by inspection.


Because assert() can be and is commonly misused, some programming language
theorists and designers look upon it with disfavor.
For example, the designers of the Go programming language 
intentionally omit a built-in assert().
They feel that the harm caused by misuse of assert()
outweighs the benefits of including it as a language built-in.
The SQLite developers disagree.  In fact, the original purpose of this
article is to push back against the common notion that assert() is harmful.
In our experience, SQLite would be much more difficult to develop, test,
and maintain without assert().


c2: The Use Of assert() In SQLite
c3: 1.2. Different Behaviors According To Build Type
c5: assert.html#different_behaviors_according_to_build_type
c4:
Three separate builds are used to validate the SQLite software.

 A functionality testing build is used to validate the source code.
 A coverage testing build is used to validate the test suite, to confirm
     that the test suite provides 100% MC/DC.
 The release build is used to validate the generated machine code.

All tests must give the same answer in all three
builds. See the "How SQLite Is Tested" document for more detail.

The various assert()-like
macros behave differently according to how SQLite is built.


Functionality TestingCoverage TestingRelease
assert(X)
abort() if X is false
no-op
no-op

ALWAYS(X)
abort() if X is false
always true
pass through the value X

NEVER(X)
abort() if X is true
always false
pass through the value X

testcase(X)
no-op
do some harmless work if X is true
no-op



The default behavior of assert(X) in standard C is that it is enabled
for release builds.  This is a reasonable default.  However, the
SQLite code base has many assert() statements in performance-sensitive
areas of the code.  Leaving assert(X) turned on causes SQLite to run about
three times slower.  Also, SQLite strives to provide 100% MC/DC in an
as-delivered configuration, which is obviously impossible if assert(X)
statements are enabled.  For these reasons, assert(X) is a no-op for
release builds in SQLite.

The ALWAYS(X) and NEVER(X) macros behave like assert(X) during
functionality testing, because the developers want to be immediately
alerted to the issue if the value of X is different from what is expected.
But for delivery, ALWAYS(X) and NEVER(X) are simple pass-through macros,
which provide defense-in-depth.  For coverage testing ALWAYS(X) and NEVER(X)
are hard-coded boolean values so that they do not cause unreachable
machine code to be generated.

The testcase(X) macro is normally a no-op, but for a coverage test
build it does generate a small amount of extra code that includes at least
one branch, in order to verify that test cases exist for which X is both
true and false.


c2: The Use Of assert() In SQLite
c3: 2. Examples
c5: assert.html#examples
c4:
An assert() statement is often used to validate pre-conditions on 
internal functions and methods.
Example: https://sqlite.org/src/artifact/c1e97e4c6f?ln=1048.
This is deemed better than simply stating the pre-condition in a header 
comment, since the assert() is actually executed.  In a highly tested
program like SQLite, the reader knows that the pre-condition is true
for all of the hundreds of millions of test cases run against SQLite,
since it has been verified by the assert().
In contrast, a text pre-condition statement in a header comment
is untested.  It might have been true when the code was written, 
but who is to say that it is still true now?


Sometimes SQLite uses compile-time evaluatable assert() statements.
Consider the code at
https://sqlite.org/src/artifact/c1e97e4c6f?ln=2130-2138.
Four assert() statements verify the values for compile-time constants
so that the reader can quickly check the validity of the if-statement
that follows, without having to look up the constant values in a separate
header file.


Sometimes compile-time assert() statements are used to verify that
SQLite has been correctly compiled.  For example, the code at
https://sqlite.org/src/artifact/c1e97e4c6f?ln=157
verifies that the SQLITE_PTRSIZE preprocessor macro is set correctly
for the target architecture.


The CORRUPT_DB macro is used in many assert() statements.
In functional testing builds, CORRUPT_DB references a global variable
that is true if the database file might contain corruption.  This variable
is true by default, since we do not normally know whether or not a database
is corrupt, but during testing while working on databases that are known
to be well-formed, that global variable can be set to false.
Then the CORRUPT_DB macro
can be used in assert() statements such as seen at
https://sqlite.org/src/artifact/18a53540aa3?ln=1679-1680.
Those assert()s specify pre-conditions to the routine that are true for
consistent database files, but which might be false if the database file
is corrupt. Knowledge of these kinds of conditions is very helpful to
readers who are trying to understand a block of code in isolation.


ALWAYS(X) and NEVER(X) functions are used in places where we always
want the test to occur even though the developers believe the value of
X is always true or false.  For example, the sqlite3BtreeCloseCursor()
routine shown must remove the closing cursor from a linked list of all
cursors.  We know that the cursor is on the list, so that the loop
must terminate by the "break" statement, but it is convenient to
use the ALWAYS(X) test at
https://sqlite.org/src/artifact/18a53540aa3?ln=4371 to prevent
running off the end of the linked list in case there is an error in some
other part of the code that has corrupted the linked list.


An ALWAYS(X) or NEVER(X) sometimes verifies pre-conditions that are
subject to change if other parts of the code are modified in
subtle ways.  At https://sqlite.org/src/artifact/18a53540aa3?ln=5512-5516
we have a test for two pre-conditions that are true only because
of the limited scope of use of the sqlite3BtreeRowCountEst() function.
Future enhancements to SQLite might use sqlite3BtreeRowCountEst() in
new ways where those preconditions no longer hold, and the NEVER()
macros will quickly alert the developers to that fact when the
situation arises.  But if, for some reason, the pre-conditions are
not satisfied in a release build, the program will still behave sanely
and will not do an undefined memory access.


The testcase() macro is often used to verify that boundary
cases of an inequality comparison are checked.  For example, at
https://sqlite.org/src/artifact/18a53540aa3?ln=5766.  These
kind of checks help to prevent off-by-one errors.
This page last modified on  2019-04-29 19:27:41 UTC


c2: Uniform Resource Identifiers
c3: 1. URI Filenames In SQLite
c5: uri.html#uri_filenames_in_sqlite
c4:
Beginning with version 3.7.7 (2011-06-23),
the SQLite database file argument to the
sqlite3_open(), sqlite3_open16(), and sqlite3_open_v2() interfaces
and to the ATTACH command can be specified
either as an ordinary filename or as a Uniform Resource Identifier or URI.
The advantage of using a URI filename is that query parameters on the URI can
be used to control details of the newly created database connection.
For example, an alternative VFS can be specified using a 
"vfs=" query parameter.
Or the database can be opened read-only by using "mode=ro" as a query
parameter.


c2: Uniform Resource Identifiers
c3: 2. Backwards Compatibility
c5: uri.html#backwards_compatibility
c4:
In order to maintain full backwards compatibility for legacy applications,
the URI filename capability is disabled by default.
URI filenames can be enabled or disabled using the SQLITE_USE_URI=1
or SQLITE_USE_URI=0 compile-time options.
The compile-time setting for URI filenames can be changed
at start-time using the sqlite3_config(SQLITE_CONFIG_URI,1)
or sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls.
Regardless of the compile-time or start-time settings, URI filenames
can be enabled for individual database connections by including the
SQLITE_OPEN_URI bit in the set of bits passed as the F parameter
to sqlite3_open_v2(N,P,F,V).



If URI filenames are recognized when the database connection is originally
opened, then URI filenames will also be recognized on ATTACH statements.
Similarly, if URI filenames are not recognized when the database connection
is first opened, they will not be recognized by ATTACH.



Since SQLite always interprets any filename that does not begin
with "file:"
as an ordinary filename regardless of the URI setting, and because it is
very unusual to have an actual file begin with "file:", 
it is safe for most applications to enable URI processing even if URI 
filenames are not currently being used.


c2: Uniform Resource Identifiers
c3: 3. URI Format
c5: uri.html#uri_format
c4:
According to RFC 3986, a URI consists
of a scheme, an authority, a path, a query string, and a fragment.  The
scheme is always required.  One of either the authority or the path is also
always required.  The query string and fragment are optional.



SQLite uses the "file:" URI syntax to identify database files.
SQLite strives to interpret file: URIs in exactly the same way as
popular web-browsers such as 
Firefox, 
Chrome, 
Safari, 
Internet Explorer, and
Opera,
and command-line programs such as 
Windows "start" and the Mac OS-X
"open" command.
A succinct summary of the URI parsing rules follows:



 The scheme of the URI must be "file:".  Any other scheme
     results in the input being treated as an ordinary filename.
 The authority may be omitted, may be blank, or may be
      "localhost".  Any other authority results in an error.
      Exception: If SQLite is compiled with SQLITE_ALLOW_URI_AUTHORITY
      then any authority value other than "localhost" is passed through to the 
      underlying operating system as a UNC filename.
 The path is optional if the authority is present.  If the authority
     is omitted then the path is required. 
 The query string is optional.  If the query string is present, then
      all query parameters are passed through into the xOpen method of
      the underlying VFS.  
 The fragment is optional.  If present, it is ignored.


Zero or more escape sequences of the form  "%HH" 
(where H represents any hexadecimal digit) can occur 
in the path, query string, or fragment.

A filename that is not a well-formed URI is interpreted as an
ordinary filename.

URIs are processed as UTF8 text.
The filename argument sqlite3_open16() is converted from UTF16 
native byte order into UTF8 prior to processing.


c2: Uniform Resource Identifiers
c3: 3.1. The URI Path
c5: uri.html#the_uri_path
c4:
The path component of the URI specifies the disk file that is the
SQLite database to be opened.  If the path component is omitted, then
the database is stored in a temporary file that will be automatically
deleted when the database connection closes.  If the authority section
is present, then the path is always an absolute pathname.  If the 
authority section is omitted, then the path is an absolute pathname if it
begins with the "/" character (ASCII code 0x2f) and is a relative
pathname otherwise.  On windows, if the absolute path begins with
"/X:/" where X is any single ASCII alphabetic
character ("a" through "z" or "A" through "Z") then the "X:"
is understood to be the drive letter of the volume containing the file,
not the toplevel directory.

An ordinary filename can usually be converted into an equivalent URI 
by the steps shown below.  The one exception is that a relative windows
pathname with a drive letter cannot be converted directly into a URI; it must
be changed into an absolute pathname first.


Convert all "?" characters into "%3f".
Convert all "#" characters into "%23".
On windows only, convert all "\" characters into "/".
Convert all sequences of two or more "/" characters into a
    single "/" character.
On windows only, if the filename begins with a drive letter, prepend
    a single "/" character.
Prepend the "file:" scheme.


c2: Uniform Resource Identifiers
c3: 3.2. Query String
c5: uri.html#query_string
c4:
A URI filename can optionally be followed by a query string.
The query string consists of text following the first "?"
character but excluding the optional fragment that begins with
"#".  The query string is divided into key/value pairs.
We usually refer to these key/value pairs as "query parameters".
Key/value pairs are separated by a single "&amp;" character.
The key comes first and is separated from the value by a single
"=" character.
Both key and value may contain %HH escape sequences.


The text of query parameters is appended to the filename argument of
the xOpen method of the VFS.
Any %HH escape sequences in the query parameters are resolved prior to
being appended to the xOpen filename.
A single zero-byte separates the xOpen filename argument from the key of
the first query parameters, each key and value, and each subsequent key
from the prior value.
The list of query parameters appended to the xOpen filename
is terminated by a single zero-length key.
Note that the value of a query parameter can be an empty string.


c2: Uniform Resource Identifiers
c3: 3.3. Recognized Query Parameters
c5: uri.html#recognized_query_parameters
c4:
Some query parameters are interpreted by the SQLite core and used to 
modify the characteristics of the new connection.  All query parameters
are always passed through into the xOpen method of the VFS even if
they are previously read and interpreted by the SQLite core.



The following query parameters are recognized by SQLite as of 
version 3.15.0 (2016-10-14).
New query parameters might be added in the future.





cache=sharedcache=private
The cache query parameter determines if the new database is opened
using shared cache mode or with a private cache.




immutable=1
The immutable query parameter is a boolean that signals to
SQLite that the underlying database file is held on read-only media
and cannot be modified, even by another process with elevated 
privileges.  SQLite always opens immutable database files
read-only and it skips all file locking and change detection
on immutable database files.  If this query parameter (or
the SQLITE_IOCAP_IMMUTABLE bit in xDeviceCharacteristics)
asserts that a database file is immutable and that file 
changes anyhow, then SQLite might return incorrect query 
results and/or SQLITE_CORRUPT errors.




mode=romode=rwmode=rwcmode=memory
The mode query parameter determines if the new database is opened
read-only, read-write, read-write and created if it does not exist, or
that the database is a pure in-memory database that never interacts with
disk, respectively.




modeof=filename
When creating a new database file during sqlite3_open_v2()
on unix systems, SQLite will try to set the permissions of the new
database file to match the existing file "filename".




nolock=1
The nolock query parameter is a boolean that disables all calls
to the xLock, xUnlock, and xCheckReservedLock methods of the VFS when true.
The nolock query parameter might be used, for example, when trying to
access a file on a filesystem that does not support file locking.
Caution:  If two or more database connections try to interact with 
the same SQLite database and one or more of those connections has
enabled "nolock", then database corruption can result.  The "nolock"
query parameter should only be used if the application can guarantee
that writes to the database are serialized.



psow=0psow=1
The psow query parameter overrides the powersafe overwrite
property of the database file being opened.  The psow query parameter
works with the default windows and unix VFSes but might be a no-op for
other proprietary or non-standard VFSes.




vfs=NAME
The vfs query parameter causes the database connection to be opened
using the VFS called NAME.
The open attempt fails if NAME is not the name of a VFS that
is built into SQLite or that has been previously registered using
sqlite3_vfs_register().


c2: Uniform Resource Identifiers
c3: 4. See Also
c5: uri.html#see_also
c4:
URI filenames in sqlite3_open()
 URI filename examples

This page last modified on  2022-01-20 21:38:08 UTC


c2: The Next-Generation Query Planner
c3: 1. Introduction
c5: queryplanner-ng.html#_introduction
c4:
The task of the "query planner" is to figure
out the best algorithm or "query plan" to accomplish an SQL statement.
Beginning with SQLite version 3.8.0 (2013-08-26),
the query planner component has been
rewritten so that it runs faster and generates better plans.  The
rewrite is called the "next generation query planner" or "NGQP".


This article overviews the importance of query planning, describes some
of the problems inherent to query planning, and outlines how the NGQP
solves those problems.

The NGQP is almost always better than the legacy query planner.
However, there may exist legacy applications that unknowingly depend on 
undefined and/or suboptimal behavior in the legacy query planner, and
upgrading to the NGQP on those legacy applications could cause performance
regressions.  This risk is considered and a checklist is provided
for reducing the risk and for fixing any issues that do arise.

This document focuses on the NGQP.  For a more general overview of the
SQLite query planner that encompasses the entire history of SQLite, see the
"The SQLite Query Optimizer Overview" and
"How Indexes Work" documents.


c2: The Next-Generation Query Planner
c3: 2. Background
c5: queryplanner-ng.html#_background
c4:
For simple queries against a single table with few indexes, there is usually
an obvious choice for the best algorithm.
But for larger and more complex queries, such as
multi-way joins with many indexes
and subqueries, there can be hundreds, thousands, or millions
of reasonable algorithms for computing the result.
The job of the query planner is to choose the single "best" query plan from
this multitude of possibilities.

Query planners are what make SQL database engines so amazingly useful and powerful.
(This is true of all SQL database engines, not just SQLite.)
The query planner frees the programmer from the chore of selecting
a particular query plan, and thereby allows the programmer to
focus more mental energy on higher-level application issues and on 
providing more value to the end user.  For simple queries where the choice
of query plan is obvious, this is convenient but not hugely important.
But as applications and schemas and queries grow more complex, a
clever query planner can greatly speed and simplify the work of application
development. 
There is amazing power in being about to tell
the database engine what content is desired, and then let the database
engine figure out the best way to retrieve that content.

Writing a good query planner is more art than science.
The query planner must work with incomplete information.
It cannot determine how long any particular plan will take
without actually running that plan.  So when comparing two
or more plans to figure out which is "best", the query planner has to make
some guesses and assumptions and those guesses and assumptions will 
sometimes be wrong. A good query planner is one that will
find the correct solution often enough that application
programmers rarely need to get involved.


c2: The Next-Generation Query Planner
c3: 2.1. Query Planning In SQLite
c5: queryplanner-ng.html#_query_planning_in_sqlite
c4:
SQLite computes joins using nested loops, 
one loop for each table
in the join.  (Additional loops might be inserted for IN
and OR operators in the WHERE clause.  SQLite considers those too,
but for simplicity we will ignore them in this essay.)
One or more indexes might be used on each loop to speed the search,
or a loop might be a "full table scan" that reads every row in the
table.  Thus query planning decomposes into two subtasks:

 Picking the nested order of the various loops
 Choosing good indexes for each loop

Picking the nesting order is generally the more challenging problem.
Once the nesting order of the join is established, the choice of indexes
for each loop is normally obvious.


c2: The Next-Generation Query Planner
c3: 2.2. The SQLite Query Planner Stability Guarantee
c5: queryplanner-ng.html#_the_sqlite_query_planner_stability_guarantee
c4:
When the Query Planner Stability Guarantee (QPSG) is enabled
SQLite will always pick the same query plan for any
given SQL statement as long as:


the database schema does not change in significant ways such as 
    adding or dropping indexes,
the ANALYZE command is not rerun, 
the same version of SQLite is used.


The QPSG is disabled by default.  It can be enabled at compile-time
using the SQLITE_ENABLE_QPSG compile-time option, or at run-time by
invoking sqlite3_db_config(db,SQLITE_DBCONFIG_ENABLE_QPSG,1,0).

The QPSG means that if all of your queries run efficiently
during testing, and if your application does not change the schema,
then SQLite will not suddenly decide to start using a different
query plan, possibly causing a performance problem after your application 
is released to users.  If your application works in the lab, it
will continue working the same way after deployment.

Enterprise-class client/server SQL database engines do not normally 
make this guarantee.
In client/server SQL database engines, the server keeps track of
statistics on the sizes of tables and on the quality of indexes 
and the query planner uses those statistics to help select the best plans.
As content is added, deleted, or changed in the database, the statistics 
will evolve and may cause the query planner to begin using a different 
query plan for some particular query.  Usually the new plan will be better 
for the evolving structure of the data.  But sometimes the new query plan will
cause a performance reduction.  With a client/server database engine, there
is typically a Database Administrator (DBA) on hand to deal with these 
rare problems as they come up.  But DBAs are not available to fix problems 
in an embedded database like SQLite, and hence SQLite is careful to
ensure that plans do not change unexpectedly after deployment.

It is important to note that changing versions of SQLite might cause
changes in query plans.
The same version of SQLite will
always pick the same query plan, but if you relink your application to use
a different version of SQLite, then query plans might change.  In rare
cases, an SQLite version change might lead to a performance regression.  
This is one reason
you should consider statically linking your applications against SQLite 
rather than use a system-wide SQLite shared library which might 
change without your knowledge or control.


c2: The Next-Generation Query Planner
c3: 3. A Difficult Case
c5: queryplanner-ng.html#_a_difficult_case
c4:
"TPC-H Q8" is a test query from the
Transaction Processing Performance
Council.  The query planners in SQLite versions 3.7.17 and earlier 
do not choose good plans for TPC-H Q8.  And it has been determined that 
no amount
of tweaking of the legacy query planner will fix that.  In order to find
a good solution to the TPC-H Q8 query, and to continue improving the 
quality of SQLite's query planner, it became necessary to redesign the
query planner.  This section tries to explain why this redesign was
necessary and how the NGQP is different and addresses the TPC-H Q8 problem.


c2: The Next-Generation Query Planner
c3: 3.1. Query Details
c5: queryplanner-ng.html#_query_details
c4:
TPC-H Q8 is an eight-way join.
As observed above, the main task of the query planner is
to figure out the best nesting order of the eight loops in order to minimize
the work needed to complete the join.
A simplified model of this problem for the case of TPC-H Q8 is shown
by the following diagram:








In the diagram, each of the 8 tables in the FROM clause of the query is
identified by a large circle with the label of the FROM-clause term:
N2, S, L, P, O, C, N1 and R.
The arcs in the graph represent the estimated cost of computing each term 
assuming that the origin of the arc is in an outer loop.  For example, the
cost of running the S loop as an inner loop to L is 2.30 whereas the
cost of running the S loop as an outer loop to L is 9.17.

The "cost" here is logarithmic.  With nested loops, the work
is multiplied, not added.  But it is customary to think of graphs
with additive weights and so the graph shows the logarithm of the
various costs.  The graph shows a cost advantage of S being inside of
L of about 6.87, but this translates into the query running about
963 times faster when S loop is inside of the L loop rather than
being outside of it.

The arrows from the small circles labeled with "*" indicate the cost
of running each loop with no dependencies.  The outermost loop must use this
*-cost.  Inner loops have the option of using the *-cost or a cost assuming
one of the other terms is in an outer loop, whichever gives the best
result.  One can think of the *-costs as a short-hand notation indicating
multiple arcs, one from each of the other nodes in the
graph.  The graph is therefore "complete", meaning that there are arcs
(some explicit and some implied) in both directions between every pair of 
nodes in the graph.

The problem of finding the best query plan is equivalent to finding
a minimum-cost path through the graph that visits each node
exactly once.

(Side note:  The cost estimates in the TPC-H Q8 graph above were computed
by the query planner in SQLite 3.7.16 and converted using a natural logarithm.)


c2: The Next-Generation Query Planner
c3: 3.2. Complications
c5: queryplanner-ng.html#_complications
c4:
The presentation of the query planner problem above is a simplification.
The costs are estimates.  We cannot
know what the true cost of running a loop is until we actually run the loop.
SQLite makes guesses for the cost of running a loop based on
the availability of indexes and constraints found in the WHERE
clause.  These guesses are usually pretty good, but they can sometimes be
off.  Using the ANALYZE command to collect additional statistical
information about the database can sometimes enable SQLite to make better
guesses about the cost.

The costs are comprised of multiple numbers, not a single number as
shown in the graph.
SQLite computes several different estimated costs for each loop that apply at
different times.  For example, there is a "setup" cost that is incurred
just once when the query starts.  The setup cost is the cost of computing
an automatic index for a table that does not already
have an index.  Then there
is the cost of running each step of the loop.  Finally, there is an estimate
of the number rows generated by the loop, which is information needed in
estimating the costs of inner loops.  Sorting costs may come into play
if the query has an ORDER BY clause.

In a general query, dependencies need not be on a single loop, and hence
the matrix of dependencies might not be representable as a graph.
For example, one of the WHERE clause constraints might be
S.a=L.b+P.c, implying that the S loop must be an inner loop of both
L and P.  Such dependencies cannot be drawn as a graph
since there is no way for an arc to originate at two or more nodes at
once.

If the query contains an ORDER BY clause or a GROUP BY clause or if
the query uses the DISTINCT keyword then it is advantageous to select a 
path through the graph that causes rows to naturally appear in sorted order, 
so that no separate sorting step is required.  Automatic elimination of 
ORDER BY clauses
can make a large performance difference, so this is another factor
that needs to be considered in a complete implementation.

In the TPC-H Q8 query, the setup costs are all negligible,
all dependencies are between individual nodes, and there is no ORDER BY,
GROUP BY, or DISTINCT clause. So for TPC-H Q8,
the graph above is a reasonable representation of what needs to be computed.
The general case involves a lot of extra complication, which for clarity
is neglected in the remainder of this article.


c2: The Next-Generation Query Planner
c3: 3.3. Finding The Best Query Plan
c5: queryplanner-ng.html#_finding_the_best_query_plan
c4:
Prior to version 3.8.0 (2013-08-26), SQLite always used
the "Nearest Neighbor" or "NN" heuristic when searching for the best query plan.
The NN heuristic makes a single traversal of the graph, always choosing
the lowest-cost arc as the next step.  
The NN heuristic works surprisingly well in most cases.
And NN is fast, so that SQLite is able to quickly find good plans
for even large 64-way joins.  In contrast, other SQL database engines that
do more extensive searching tend to bog down when the
number of tables in a join goes above 10 or 15.

Unfortunately, the query plan computed by NN for TPC-H Q8 is not optimal.
The plan computed using NN is R-N1-N2-S-C-O-L-P with a cost of 36.92.  
The notation
in the previous sentence means that the R table is run in the outer loop,
N1 is in the next inner loop, N2 is in the third loop, and so forth down
to P which is in the inner-most loop.  The shortest path through the
graph (as found via exhaustive search) is  P-L-O-C-N1-R-S-N2
with a cost of 27.38.  The difference might not seem like much, but 
remember that
the costs are logarithmic, so the shortest path is nearly 750 times
faster than that path found using the NN heuristic.

One solution to this problem is to change SQLite to do an exhaustive
search for the best path.  But an exhaustive search requires time 
proportional to
K! (where K is the number of tables in the join) and so when you get 
beyond a 10-way join, the time
to run sqlite3_prepare() becomes very large.


c2: The Next-Generation Query Planner
c3: 3.4. The N Nearest Neighbors or "N3" Heuristic
c5: queryplanner-ng.html#_the_n_nearest_neighbors_or_n3_heuristic
c4:
The NGQP uses a new heuristic for seeking the best path through the
graph: "N Nearest Neighbors" (hereafter "N3").  With N3, instead of
choosing just one nearest neighbor for each step, the algorithm keeps
track of the N bests paths at each step for some small integer N.

Suppose N=4.  Then for the TPC-H Q8 graph, the first step finds
the four shortest paths to visit any single node in the graph:


    R (cost: 3.56) 
    N1 (cost: 5.52) 
    N2 (cost: 5.52) 
    P (cost: 7.71) 


The second step finds the four shortest paths to visit two nodes 
beginning with one of the four paths from the previous step.  In the
case where two or more paths are equivalent (they have the same set of
visited nodes, though possibly in a different order) only the
first and lowest-cost path is retained.  We have:


    R-N1 (cost: 7.03) 
    R-N2 (cost: 9.08) 
    N2-N1 (cost: 11.04) 
    R-P {cost: 11.27} 


The third step starts with the four shortest two-node paths and finds
the four shortest three-node paths:


    R-N1-N2 (cost: 12.55) 
    R-N1-C (cost: 13.43) 
    R-N1-P (cost: 14.74) 
    R-N2-S (cost: 15.08) 


And so forth.  There are 8 nodes in the TPC-H Q8 query, 
so this process repeats a total of 8
times.  In the general case of a K-way join, the storage requirement
is O(N) and the computation time is O(K*N), which is significantly faster
than the O(2K) exact solution.

But what value to choose for N?  One might try N=K.  This makes the
algorithm O(K2) 
which is actually still quite efficient, since the
maximum value of K is 64 and K rarely exceeds 10.  
But that is not enough for the TPC-H Q8
problem.  With N=8 on TPC-H Q8 the N3 algorithm finds 
the solution R-N1-C-O-L-S-N2-P with a cost of 29.78.  
That is a big improvement over NN, but it is still
not optimal.  N3 finds the optimal solution for TPC-H Q8 
when N is 10 or greater.

The initial implementation of NGQP chooses N=1 for simple queries, N=5
for two-way joins and N=10 for all joins with three or more tables.  This
formula for selecting N might change in subsequent releases.


c2: The Next-Generation Query Planner
c3: 4. Hazards Of Upgrading To NGQP
c5: queryplanner-ng.html#_hazards_of_upgrading_to_ngqp
c4:
Update on 2018-11-24: This section was important 
when the NGQP was new.  But five years have elapsed, the NGQP has been
deployed successfully to billions of devices, and everyone has upgraded.
The upgrade hazard has vanished.
This section is retained for historical reference only.
Modern reads can skip ahead to the query planner checklist.

For most applications, upgrading from the legacy query planner to the NGQP
requires little thought or effort.
Simply replace the older SQLite version with the newer version of SQLite 
and recompile and the application will run faster.  
There are no API changes nor modifications
to compilation procedures.

But as with any query planner change, upgrading to the NGQP does carry
a small risk of introducing performance regressions.  The problem here is
not that the NGQP is incorrect or buggy or inferior to the legacy query
planner.  Given reliable information about the selectivity of indexes, 
the NGQP should always pick a plan that is as good or better than before.
The problem is that some applications may be using low-quality and
low-selectivity indexes without having run ANALYZE.  The older query
planners look at many fewer possible implementations for each query and 
so they may have stumbled over a good plan by stupid luck.  The NGQP, on 
the other hand, looks at many more query plan possibilities, and it may 
choose a different query plan that
works better in theory, assuming good indexes, but which gives a performance
regression in practice, because of the shape of the data.

Key points:


The NGQP will always find an equal or better query plan, compared to
    prior query planners, as long as it
    has access to accurate ANALYZE data in the SQLITE_STAT1 file.
The NGQP will always find a good query plan 
    as long as the schema does not contain indexes that have more than
    about 10 or 20 rows with the same value in the left-most column of the
    index.


Not all applications meet these conditions.  Fortunately,
the NGQP will still usually find good query plans, even without these conditions.
However, cases do arise (rarely) where performance regressions can occur.


c2: The Next-Generation Query Planner
c3: 4.1. Case Study: Upgrading Fossil to the NGQP
c5: queryplanner-ng.html#_case_study_upgrading_fossil_to_the_ngqp
c4:
The Fossil DVCS is the version
control system used to track all of the SQLite source code.
A Fossil repository is an SQLite database file.
(Readers are invited to ponder this recursion as an independent exercise.)
Fossil is both the version-control system for SQLite and a test
platform for SQLite.  Whenever enhancements are made to SQLite, 
Fossil is one of the first applications to test and evaluate those
enhancements.  So Fossil was an early adopter of the NGQP.

Unfortunately, the NGQP caused a
performance regression in Fossil.

One of the many reports that Fossil makes available is a timeline of
changes to a single branch showing all merges in and out of that branch.  See
http://www.sqlite.org/src/timeline?nd&n=200&r=trunk
for a typical
example of such a report.  Generating such a report normally takes just
a few milliseconds.  But after upgrading to the NGQP we noticed that
this one report was taking closer to 10 seconds for the trunk of the
repository.

The core query used to generate the branch timeline is shown below.
(Readers are not expected to understand the details of this query.
Commentary will follow.)


SELECT
     blob.rid AS blobRid,
     uuid AS uuid,
     datetime(event.mtime,'localtime') AS timestamp,
     coalesce(ecomment, comment) AS comment,
     coalesce(euser, user) AS user,
     blob.rid IN leaf AS leaf,
     bgcolor AS bgColor,
     event.type AS eventType,
     (SELECT group_concat(substr(tagname,5), ', ')
        FROM tag, tagxref
       WHERE tagname GLOB 'sym-*'
         AND tag.tagid=tagxref.tagid
         AND tagxref.rid=blob.rid
         AND tagxref.tagtype>0) AS tags,
     tagid AS tagid,
     brief AS brief,
     event.mtime AS mtime
  FROM event CROSS JOIN blob
 WHERE blob.rid=event.objid
   AND (EXISTS(SELECT 1 FROM tagxref
                WHERE tagid=11 AND tagtype>0 AND rid=blob.rid)
        OR EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=cid
                   WHERE tagid=11 AND tagtype>0 AND pid=blob.rid)
        OR EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid
                   WHERE tagid=11 AND tagtype>0 AND cid=blob.rid))
 ORDER BY event.mtime DESC
 LIMIT 200;


This query is not
especially complicated, but even so it replaces hundreds or 
perhaps thousands of lines of procedural code.
The gist of the query is this:  Scan down the EVENT table looking
for the most recent 200 check-ins that satisfy any one of three conditions:


 The check-in has a "trunk" tag.
 The check-in has a child that has a "trunk" tag.
 The check-in has a parent that has a "trunk" tag.



The first condition causes all of the trunk check-ins to be displayed and
the second and third cause check-ins that merge into or fork from
the trunk to also be included.
The three conditions are implemented by the three OR-connected
EXISTS statements in the WHERE clause of the query.
The slowdown that occurred with the NGQP was caused by the second and
third conditions.  The problem is the same in each, so we will examine
just the second one.
The subquery of the second condition can be rewritten (with minor
and immaterial simplifications) as follows:


SELECT 1
  FROM plink JOIN tagxref ON tagxref.rid=plink.cid
 WHERE tagxref.tagid=$trunk
   AND plink.pid=$ckid;


The PLINK table holds parent-child relationships between
check-ins.  The TAGXREF table maps tags into check-ins.
For reference, the relevant portions of the schemas
for these two tables is shown here:


CREATE TABLE plink(
  pid INTEGER REFERENCES blob,
  cid INTEGER REFERENCES blob
);
CREATE UNIQUE INDEX plink_i1 ON plink(pid,cid);

CREATE TABLE tagxref(
  tagid INTEGER REFERENCES tag,
  mtime TIMESTAMP,
  rid INTEGER REFERENCE blob,
  UNIQUE(rid, tagid)
);
CREATE INDEX tagxref_i1 ON tagxref(tagid, mtime);


There are only two reasonable ways to implement this query.
(There are many other possible algorithms, but none of the
others are contenders for being the "best" algorithm.)



Find all children of check-in $ckid and test each one to see if
it has the $trunk tag.

Find all check-ins with the $trunk tag and test each one to see if
it is a child of $ckid.



Intuitively, we humans understand that algorithm-1 is best.
Each check-in is likely to have few children (one child is
the most common case) and each child can be tested for the
$trunk tag in logarithmic time.  Indeed, algorithm-1 is the
faster choice in practice.  But the NGQP has no intuition.  The
NGQP must use hard math, and algorithm-2 is slightly
better mathematically.  This is because, in the absence of other information,
the NGQP must assume that the indexes PLINK_I1 and TAGXREF_I1 are of
equal quality and are equally selective.  Algorithm-2 uses one field
of the TAGXREF_I1 index and both fields of the PLINK_I1 index whereas
algorithm-1 only uses the first field of each index.  Since 
algorithm-2 uses more index material, the NGQP is correct
to judge it to be the better algorithm.  The scores are close and
algorithm-2 just barely squeaks ahead of algorithm-1.  But
algorithm-2 really is the correct choice here.



Unfortunately, algorithm-2 is slower than algorithm-1 in
this application.



The problem is that the indexes are not of equal quality.
A check-in is likely to only have one child.  So the first
field of PLINK_I1 will usually narrow down the search to just a single
row.  But there are thousands and thousands check-ins tagged with "trunk", 
so the first field of TAGXREF_I1 will be
of little help in narrowing down the search.



The NGQP has no way of knowing that TAGXREF_I1 is almost useless in this
query, unless ANALYZE has been run on the database.  The ANALYZE command
gathers statistics on the quality of the various indexes and stores those
statistics in SQLITE_STAT1 table.  
Having access to this statistical information,
the NGQP easily chooses algorithm-1 as the best algorithm, by a wide
margin.

Why didn't the legacy query planner choose algorithm-2?
Easy: because the NN algorithm
never even considered algorithm-2.  Graphs of the planning
problem look like this:







In the "without ANALYZE" case on the left, the NN algorithm chooses 
loop P (PLINK) as the outer loop because 4.9 is less than 5.2, resulting
in path P-T which is algorithm-1. NN only looks at the single best choice
at each step so it completely misses the fact that 
5.2+4.4 makes a slightly cheaper plan than 4.9+4.8. But the N3 algorithm
keeps track of the 5 best paths for a 2-way join, so it ends up
selecting path T-P because of its slightly lower overall cost.
Path T-P is algorithm-2.



Note that with ANALYZE the cost estimates are
better aligned with reality and algorithm-1 is 
selected by both NN and N3.


(Side note:  The costs estimates in the two most recent graphs 
were computed by the NGQP using a base-2 logarithm and slightly different
cost assumptions compared to the legacy query planner.  
Hence, the cost estimates in
these latter two graphs are not directly comparable to the cost estimates
in the TPC-H Q8 graph.)


c2: The Next-Generation Query Planner
c3: 4.2. Fixing The Problem
c5: queryplanner-ng.html#_fixing_the_problem
c4:
Running ANALYZE on the repository database immediately fixed the
performance problem.  However, we want Fossil to be robust and to always
work quickly regardless of whether or not its repository has been analyzed.
For this reason, the query was modified to use the CROSS JOIN operator 
instead of the plain JOIN operator.
SQLite will not reorder the tables of a CROSS JOIN.
This is a long-standing feature of SQLite that is specifically designed
to allow knowledgeable programmers
to enforce a particular loop nesting order.  Once the join
was changed to CROSS JOIN (the addition of a single keyword) the NGQP was
forced to choose the faster algorithm-1 regardless of whether or not
statistical information had been gathered using ANALYZE.

We say that algorithm-1 is "faster", but this
is not strictly true.  Algorithm-1 is faster in common repositories, but
it is possible to construct a repository in which
every check-in is on a different uniquely-named branch and
all check-ins are children of the root check-in.
In that case, TAGXREF_I1 would become more selective
than PLINK_I1 and algorithm-2 really would be the faster choice.
However such repositories are very unlikely to appear in
practice and so hard-coding the loop nested order using the
CROSS JOIN syntax is a reasonable solution
to the problem in this case.


c2: The Next-Generation Query Planner
c3: 4.3. Update 2017: A Better Fix
c5: queryplanner-ng.html#update_2017_a_better_fix
c4:
The prior text was written in early 2013, before the first release of
SQLite version 3.8.0.  This paragraph was added in mid 2021.
While all of the previous discussion remains true, a lot of improvements
have been made to the query planner, making this whole section largely moot.

In 2017, Fossil was enhanced to make use of the new
PRAGMA optimize statement.  Whenever Fossil is about to close the
database connection to its repository, it first runs
"PRAGMA optimize", which will in turn cause ANALYZE to be run if it
is needed.  Usually an ANALYZE is not needed, and so there is no
measurable performance penalty for doing this.  But every now and
then ANALYZE might be run on a few of the tables in the repository
database.  Because if this, query planning issues such as the one
described here no longer come up in Fossil.  The fact that ANALYZE
is run periodically to keep the sqlite_stat1 table up-to-date means
that hand-tuning of queries is no longer required.  We have not had
to tweak a query in Fossil in ages.

Therefore, the current recommendation for avoiding problems such
as this one is to simply run "PRAGMA optimize" (possibly preceded by
"PRAGMA analysis_limit=200") just prior to closing each database
connection.  The CROSS JOIN hack is still available, but if you keep
the query planner statistics in the sqlite_stat1 table up-to-date,
it usually won't be necessary.


c2: The Next-Generation Query Planner
c3: 5. Checklist For Avoiding Or Fixing Query Planner Problems
c5: queryplanner-ng.html#_checklist_for_avoiding_or_fixing_query_planner_problems
c4:
Don't panic!
Cases where the query planner picks an inferior plan are actually quite
rare.  You are unlikely to run across any problems in your application.
If you are not having performance issues, you do not need to worry
about any of this.

Create appropriate indexes.
Most SQL performance problems arise not because of query planner issues
but rather due to lack of appropriate indexes.  Make sure indexes are
available to assist all large queries.  Most performance issues can be
resolved by one or two CREATE INDEX commands and with no changes to
application code.

Avoid creating low-quality indexes..
A low-quality index (for the purpose of this checklist) is one where
there are more than 10 or 20 rows in the table that have the same value
for the left-most column of the index.  In particular, avoid using
boolean or "enum" columns as the left-most columns of your indexes.

The Fossil performance problem described in the previous section of
this document arose because there were over
ten-thousand entries in the TAGXREF table with the same value for the 
left-most column (the TAGID column) of the TAGXREF_I1 index.

If you must use a low-quality index, be sure to run ANALYZE.
Low-quality indexes will not confuse the query planner as long as the
query planner knows that the indexes are of low quality.  And the way
the query planner knows this is by the content of the SQLITE_STAT1 table,
which is computed by the ANALYZE command.

Of course, ANALYZE only works effectively if you have a significant 
amount of content in your database in the first place.  When creating a 
new database that you expect to accumulate a lot of data, you can run 
the command "ANALYZE sqlite_schema" to create the SQLITE_STAT1 table,
then prepopulate the sqlite_stat1 table (using ordinary INSERT statements)
with content that describes a typical
database for your application - perhaps content that you extracted after
running ANALYZE on a well-populated template database in the lab.
Or, you could just run "PRAGMA optimize" before shutting down
database connections so that ANALYZE will be run automatically as
needed to keep the sqlite_stat1 table current.

Instrument your code.
Add logic that lets you know quickly and easily which queries are taking
too much time.  Then work on just those specific queries.

Use unlikely() and likelihood() SQL functions.
SQLite normally assumes that terms in the WHERE clause that cannot be used
by indexes have a strong probability of being true.  If this assumption
is incorrect, it could lead to a suboptimal query plan.  The
unlikely() and likelihood() SQL functions can be used to provide
hints to the query planner about WHERE clause terms that are probably
not true, and thus aid the query planner in selecting the best possible
plan.

Use the CROSS JOIN syntax to enforce a particular
loop nesting order on queries that might use low-quality indexes in an
unanalyzed database.
SQLite treats the CROSS JOIN operator specially, forcing the table to 
the left to be an outer loop relative to the table on the right.

Avoid this step if possible, as it defeats one of the huge advantages
of the whole SQL language concept, specifically that the application 
programmer does not need to get involved with query planning.  If you
do use CROSS JOIN, wait until late in your development cycle to do so,
and comment the use of CROSS JOIN carefully so that you can take it out
later if possible.  Avoid using CROSS JOIN early in the development
cycle as doing so is a premature optimization, which is well known to
be the root of
all evil.

Use unary "+" operators to disqualify WHERE clause terms.
If the query planner insists on selecting a poor-quality index for a particular
query when a much higher-quality index is available, then
careful use of unary "+" operators in the WHERE clause
can force the query planner away from the poor-quality index.
Avoid using this trick if at all possible, and especially avoid it
early in the application development cycle.  Beware that
adding a unary "+" operator to an equality expression might change
the result of that expression if 
type affinity is involved.

Use the INDEXED BY syntax to enforce the selection of
particular indexes on problem queries.
As with the previous two bullets, avoid this step if possible, and 
especially avoid doing this early in development as it is clearly a
premature optimization.


c2: The Next-Generation Query Planner
c3: 6. Summary
c5: queryplanner-ng.html#_summary
c4:
The query planner in SQLite normally does a terrific job of selecting
fast algorithms for running your SQL statements.  This is true of the 
legacy query planner and even more true of the new NGQP.  There may be
an occasional situation where, due to incomplete information, the query
planner selects a suboptimal plan.  This will happen less often with the
NGQP than with the legacy query planner, but it might still happen.  Only
in those rare cases do application developers need to get involved and
help the query planner to do the right thing.  In the common case, the
NGQP is just a new enhancement to SQLite that makes the application run
a little faster and which requires no new developer thought or action.
This page last modified on  2022-09-19 12:27:16 UTC


c2: SQLite Foreign Key Support
c3: Overview
c5: foreignkeys.html#overview
c4:
This document describes the support for SQL foreign key constraints
   introduced in SQLite version 3.6.19 (2009-10-14). 

The first section introduces the 
   concept of an SQL foreign key by example and defines the terminology 
   used for the remainder of the document. Section 2 describes the steps 
   an application must take in order to enable foreign key constraints in 
   SQLite (it is disabled by default). The next section, section 3, 
   describes the indexes that the user must create in order to use 
   foreign key constraints, and those that should be created in order for
   foreign key constraints to function efficiently. Section 4 describes
   the advanced foreign key related features supported by SQLite and
   section 5 describes the way the ALTER and DROP TABLE commands are
   enhanced to support foreign key constraints. Finally, section 6 
   enumerates the missing features and limits of the current implementation.

This document does not contain a full description of the syntax used
   to create foreign key constraints in SQLite. This may be found as 
   part of the documentation for the CREATE TABLE statement.


c2: SQLite Foreign Key Support
c3: 1. Introduction to Foreign Key Constraints
c5: foreignkeys.html#fk_basics
c4:
SQL foreign key constraints are used to enforce "exists" relationships 
    between tables. For example, consider a database schema created using 
    the following SQL commands:

CREATE TABLE artist(
  artistid    INTEGER PRIMARY KEY, 
  artistname  TEXT
);
CREATE TABLE track(
  trackid     INTEGER,
  trackname   TEXT, 
  trackartist INTEGER     -- Must map to an artist.artistid!
);


  
    The applications using this database are entitled to assume that for
    each row in the track table there exists a corresponding row in the
    artist table. After all, the comment in the declaration says so.
    Unfortunately, if a user edits the database using an external tool or 
    if there is a bug in an application, rows might be inserted into the 
    track table that do not correspond to any row in the artist
    table. Or rows might be deleted from the artist table, leaving
    orphaned rows in the track table that do not correspond to any of
    the remaining rows in artist. This might cause the application
    or applications to malfunction later on, or at least make coding the
    application more difficult.

  
    One solution is to add an SQL foreign key constraint to the database 
    schema to enforce the relationship between the artist and 
    track table. To do so, a foreign key definition may be added
    by modifying the declaration of the track table to the following:

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);


  
    This way, the constraint is enforced by SQLite. Attempting to insert
    a row into the track table that does not correspond to any
    row in the artist table will fail, as will attempting to
    delete a row from the artist table when there exist dependent 
    rows in the track table There is one exception: if the foreign
    key column in the track table is NULL, then no corresponding
    entry in the artist table is required. Expressed in SQL, this
    means that for every row in the track table, the following
    expression evaluates to true:
trackartist IS NULL OR EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist)


  Tip: If the application requires a stricter relationship between 
     artist and track, where NULL values are not permitted 
     in the trackartist column, simply add the appropriate 
     "NOT NULL" constraint to the schema.

  There are several other ways to add an equivalent foreign key declaration 
     to a CREATE TABLE statement. Refer to the 
     CREATE TABLE documentation for details.

  The following SQLite command-line session illustrates the effect of the
     foreign key constraint added to the track table:

sqlite&gt; SELECT * FROM artist;
artistid  artistname       
--------  -----------------
1         Dean Martin      
2         Frank Sinatra    

sqlite> SELECT * FROM track;
trackid  trackname          trackartist
-------  -----------------  -----------
11       That's Amore       1  
12       Christmas Blues    1  
13       My Way             2  

sqlite&gt; -- This fails because the value inserted into the trackartist column (3)
sqlite&gt; -- does not correspond to row in the artist table.
sqlite&gt; INSERT INTO track VALUES(14, 'Mr. Bojangles', 3);
SQL error: foreign key constraint failed

sqlite&gt; -- This succeeds because a NULL is inserted into trackartist. A
sqlite&gt; -- corresponding row in the artist table is not required in this case.
sqlite&gt; INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL);

sqlite&gt; -- Trying to modify the trackartist field of the record after it has 
sqlite&gt; -- been inserted does not work either, since the new value of trackartist (3)
sqlite&gt; -- Still does not correspond to any row in the artist table.
sqlite&gt; UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles';
SQL error: foreign key constraint failed

sqlite&gt; -- Insert the required row into the artist table. It is then possible to
sqlite&gt; -- update the inserted row to set trackartist to 3 (since a corresponding
sqlite&gt; -- row in the artist table now exists).
sqlite&gt; INSERT INTO artist VALUES(3, 'Sammy Davis Jr.');
sqlite&gt; UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles';

sqlite&gt; -- Now that "Sammy Davis Jr." (artistid = 3) has been added to the database,
sqlite&gt; -- it is possible to INSERT new tracks using this artist without violating
sqlite&gt; -- the foreign key constraint:
sqlite&gt; INSERT INTO track VALUES(15, 'Boogie Woogie', 3);


  
    As you would expect, it is not possible to manipulate the database to a state
    that violates the foreign key constraint by deleting or updating rows in the 
    artist table either:
sqlite&gt; -- Attempting to delete the artist record for "Frank Sinatra" fails, since
sqlite&gt; -- the track table contains a row that refer to it.
sqlite&gt; DELETE FROM artist WHERE artistname = 'Frank Sinatra';
SQL error: foreign key constraint failed

sqlite&gt; -- Delete all the records from the track table that refer to the artist
sqlite&gt; -- "Frank Sinatra". Only then is it possible to delete the artist.
sqlite&gt; DELETE FROM track WHERE trackname = 'My Way';
sqlite&gt; DELETE FROM artist WHERE artistname = 'Frank Sinatra';

sqlite&gt; -- Try to update the artistid of a row in the artist table while there
sqlite&gt; -- exists records in the track table that refer to it. 
sqlite&gt; UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin';
SQL error: foreign key constraint failed

sqlite&gt; -- Once all the records that refer to a row in the artist table have
sqlite&gt; -- been deleted, it is possible to modify the artistid of the row.
sqlite&gt; DELETE FROM track WHERE trackname IN('That''s Amore', 'Christmas Blues');
sqlite&gt; UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin';


  
    SQLite uses the following terminology:


  
    The parent table is the table that a foreign key constraint
        refers to. The parent table in the example in this section is the
        artist table. Some books and articles refer to this as the
        referenced table, which is arguably more correct, but tends
        to lead to confusion.

    The child table is the table that a foreign key constraint
        is applied to and the table that contains the REFERENCES clause.
        The example in this section uses the track table
        as the child table. Other books and articles refer to this as the
        referencing table.

    The parent key is the column or set of columns in the parent 
        table that the foreign key constraint refers to. This is normally, but
        not always, the primary key of the parent table.  The parent key must
        be a named column or columns in the parent table, not the rowid.

    The child key is the column or set of columns in the child 
        table that are constrained by the foreign key constraint and which
        hold the REFERENCES clause.
  

  
    The foreign key constraint is satisfied if for each row in the child table 
    either one or more of the child key columns are NULL, or there exists a 
    row in the parent table for which each parent key column contains a value
    equal to the value in its associated child key column.

  
    In the above paragraph, the term "equal" means equal when values are 
    compared using the rules specified 
    here. The following clarifications apply:
    
  
    When comparing text values, the collating sequence
        associated with the parent key column is always used.
    When comparing values, if the parent key column has an affinity,
        then that affinity is applied to the child key value before the
        comparison is performed.


c2: SQLite Foreign Key Support
c3: 2. Enabling Foreign Key Support
c5: foreignkeys.html#fk_enable
c4:
In order to use foreign key constraints in SQLite, the library must
    be compiled with neither SQLITE_OMIT_FOREIGN_KEY nor 
    SQLITE_OMIT_TRIGGER defined. If SQLITE_OMIT_TRIGGER is defined 
    but SQLITE_OMIT_FOREIGN_KEY is not, then SQLite behaves as it did prior 
    to version 3.6.19 (2009-10-14)
    - foreign key definitions are parsed and may be 
    queried using PRAGMA foreign_key_list, but foreign key constraints 
    are not enforced. The PRAGMA foreign_keys command is a no-op in this 
    configuration. If OMIT_FOREIGN_KEY is defined, then foreign key 
    definitions cannot even be parsed (attempting to specify a foreign
    key definition is a syntax error).

  
    Assuming the library is compiled with foreign key constraints enabled,
    it must still be enabled by the application at runtime, using the
    PRAGMA foreign_keys command. For example:

sqlite&gt; PRAGMA foreign_keys = ON;


  
    Foreign key constraints are disabled by default 
    (for backwards compatibility),
    so must be enabled separately for each database connection.
    (Note, however, that future releases of SQLite might change
    so that foreign key constraints enabled by default.  Careful
    developers will not
    make any assumptions about whether or not foreign keys are enabled by
    default but will instead enable or disable them as necessary.)
    The application can also use a PRAGMA foreign_keys statement to
    determine if foreign keys are currently enabled. The following 
    command-line session demonstrates this:
sqlite> PRAGMA foreign_keys;
0
sqlite> PRAGMA foreign_keys = ON;
sqlite> PRAGMA foreign_keys;
1
sqlite> PRAGMA foreign_keys = OFF;
sqlite> PRAGMA foreign_keys;
0


  Tip: If the command "PRAGMA foreign_keys" returns no data instead of a
     single row containing "0" or "1", then the version of SQLite you are
     using does not support foreign keys (either because it is older than
     3.6.19 or because it was compiled with SQLITE_OMIT_FOREIGN_KEY or 
     SQLITE_OMIT_TRIGGER defined).

  
    It is not possible to enable or disable foreign key constraints
    in the middle of a multi-statement transaction (when SQLite
    is not in autocommit mode).  Attempting to do so does not return
    an error; it simply has no effect.


c2: SQLite Foreign Key Support
c3: 3. Required and Suggested Database Indexes
c5: foreignkeys.html#fk_indexes
c4:
Usually, the parent key of a foreign key constraint is the primary key of
    the parent table. If they are not the primary key, then the parent key
    columns must be collectively subject to a UNIQUE constraint or have
    a UNIQUE index. 
    If the parent key columns have a UNIQUE index,
    then that index must use the collation sequences that are specified
    in the CREATE TABLE statement for the parent table.
    For example,

CREATE TABLE parent(a PRIMARY KEY, b UNIQUE, c, d, e, f);
CREATE UNIQUE INDEX i1 ON parent(c, d);
CREATE INDEX i2 ON parent(e);
CREATE UNIQUE INDEX i3 ON parent(f COLLATE nocase);

CREATE TABLE child1(f, g REFERENCES parent(a));                        -- Ok
CREATE TABLE child2(h, i REFERENCES parent(b));                        -- Ok
CREATE TABLE child3(j, k, FOREIGN KEY(j, k) REFERENCES parent(c, d));  -- Ok
CREATE TABLE child4(l, m REFERENCES parent(e));                        -- Error!
CREATE TABLE child5(n, o REFERENCES parent(f));                        -- Error!
CREATE TABLE child6(p, q, FOREIGN KEY(p, q) REFERENCES parent(b, c));  -- Error!
CREATE TABLE child7(r REFERENCES parent(c));                           -- Error!


  
    The foreign key constraints created as part of tables child1, 
    child2 and child3 are all fine. The foreign key
    declared as part of table child4 is an error because even though
    the parent key column is indexed, the index is not UNIQUE.
    The foreign key for table child5
    is an error because even though the parent key column has a unique
    index, the index uses a different collating sequence.
    Tables child6 and child7 are incorrect because while
    both have UNIQUE indices on their parent keys, the keys are not an
    exact match to the columns of a single UNIQUE index.

  
    If the database schema contains foreign key errors that require looking
    at more than one table definition to identify, then those errors are not
    detected when the tables are created. Instead, such errors prevent
    the application from preparing SQL statements that modify the content
    of the child or parent tables in ways that use the foreign keys.
    Errors reported when content is changed are "DML errors" and errors
    reported when the schema is changed are "DDL errors".
    So, in other words, misconfigured foreign key constraints that require
    looking at both the child and parent are DML errors.
    The English language error message for foreign key DML errors is usually
    "foreign key mismatch" but can also be "no such table" if the parent
    table does not exist.
    Foreign key DML errors are reported if:

  
     The parent table does not exist, or
     The parent key columns named in the foreign key constraint do
         not exist, or
     The parent key columns named in the foreign key constraint are not
         the primary key of the parent table and are not subject to a unique
         constraint using collating sequence specified in the CREATE TABLE, or
     The child table references the primary key of the parent without
         specifying the primary key columns and the number of primary key
         columns in the parent do not match the number of child key columns.
  

  
    The last bullet above is illustrated by the following:

CREATE TABLE parent2(a, b, PRIMARY KEY(a,b));

CREATE TABLE child8(x, y, FOREIGN KEY(x,y) REFERENCES parent2);        -- Ok
CREATE TABLE child9(x REFERENCES parent2);                             -- Error!
CREATE TABLE child10(x,y,z, FOREIGN KEY(x,y,z) REFERENCES parent2);    -- Error!


  
    By contrast, if foreign key errors can be recognized simply by looking
    at the definition of the child table and without having to consult the
    parent table definition, then the 
    CREATE TABLE statement for the child table fails.  Because the error
    occurs during a schema change, this is a DDL error.
    Foreign key DDL errors are reported regardless of
    whether or not foreign key constraints are enabled when the
    table is created.

  
    Indices are not required for child key columns but they are almost
    always beneficial. Returning to
    the example in section 1, each time an application
    deletes a row from the artist table (the parent table), it
    performs the equivalent of the following SELECT statement to search
    for referencing rows in the track table (the child table).

SELECT rowid FROM track WHERE trackartist = ?


 
   where ? in the above is replaced with the value of the artistid
   column of the record being deleted from the artist table (recall
   that the trackartist column is the child key and the artistid
   column is the parent key). Or, more generally:

SELECT rowid FROM &lt;child-table&gt; WHERE &lt;child-key&gt; = :parent_key_value


 
   If this SELECT returns any rows at all, then SQLite concludes that
   deleting the row from the parent table would violate the foreign key
   constraint and returns an error.
   Similar queries may be run if the content of the parent key
   is modified or a new row is inserted into the parent table.
   If these queries cannot use an index, they are forced to do a
   linear scan of the entire child table.  In a non-trivial database, this may
   be prohibitively expensive.

 
   So, in most real systems, an index should be created on the child key columns
   of each foreign key constraint. The child key index does not have
   to be (and usually will not be) a UNIQUE index.
   Returning again to the example in section 1, the
   complete database schema for efficient implementation of the foreign key 
   constraint might be:

CREATE TABLE artist(
  artistid    INTEGER PRIMARY KEY, 
  artistname  TEXT
);
CREATE TABLE track(
  trackid     INTEGER,
  trackname   TEXT, 
  trackartist INTEGER REFERENCES artist
);
CREATE INDEX trackindex ON track(trackartist);


  
    The block above uses a shorthand form to create the foreign key constraint.
    Attaching a "REFERENCES &lt;parent-table&gt;" clause to a column
    definition creates a foreign key constraint that maps the column to the
    primary key of &lt;parent-table&gt;. Refer to the CREATE TABLE 
    documentation for further details.


c2: SQLite Foreign Key Support
c3: 4.1. Composite Foreign Key Constraints
c5: foreignkeys.html#fk_composite
c4:
A composite foreign key constraint is one where the child and parent keys
    are both composite keys. For example, consider
    the following database schema:

CREATE TABLE album(
  albumartist TEXT,
  albumname TEXT,
  albumcover BINARY,
  PRIMARY KEY(albumartist, albumname)
);

CREATE TABLE song(
  songid     INTEGER,
  songartist TEXT,
  songalbum TEXT,
  songname   TEXT,
  FOREIGN KEY(songartist, songalbum) REFERENCES album(albumartist, albumname)
);


  
    In this system, each entry in the song table is required to map to an entry
    in the album table with the same combination of artist and album.

  
    Parent and child keys must have the same cardinality.
    In SQLite, if any of the child key columns (in this case songartist 
    and songalbum) are NULL, then there is no requirement for a corresponding
    row in the parent table.


c2: SQLite Foreign Key Support
c3: 4.2. Deferred Foreign Key Constraints
c5: foreignkeys.html#fk_deferred
c4:
Each foreign key constraint in SQLite is classified as either immediate
     or deferred. Foreign key constraints are immediate by default.
     All the foreign key examples presented
     so far have been of immediate foreign key constraints.

  
    If a statement modifies the contents of the database so that an immediate 
    foreign key constraint is in violation at the conclusion the statement, 
    an exception is thrown and 
    the effects of the statement are reverted. By contrast, if
    a statement modifies the contents of the database such that a deferred 
    foreign key constraint is violated, the violation is not reported
    immediately. Deferred foreign key constraints are not checked
    until the transaction tries to COMMIT.
    For as long as the user has 
    an open transaction, the database is allowed to exist in a state that 
    violates any number of deferred foreign key constraints. However, 
    COMMIT will fail as long as foreign key constraints remain in
    violation.

  
    If the current statement is not inside an explicit transaction (a 
    BEGIN/COMMIT/ROLLBACK block), then an implicit
    transaction is committed
    as soon as the statement has finished executing. In this case deferred
    constraints behave the same as immediate constraints.

  
    To mark a foreign key constraint as deferred, its declaration must
    include the following clause:

DEFERRABLE INITIALLY DEFERRED                -- A deferred foreign key constraint


  
    The full syntax for specifying foreign key constraints is available as part
    of the CREATE TABLE documentation. Replacing the phrase above
    with any of the following 
    creates an immediate foreign key constraint.

NOT DEFERRABLE INITIALLY DEFERRED            -- An immediate foreign key constraint
NOT DEFERRABLE INITIALLY IMMEDIATE           -- An immediate foreign key constraint
NOT DEFERRABLE                               -- An immediate foreign key constraint
DEFERRABLE INITIALLY IMMEDIATE               -- An immediate foreign key constraint
DEFERRABLE                                   -- An immediate foreign key constraint


  The defer_foreign_keys pragma can be used to temporarily change all foreign
    key constraints to deferred regardless of how they are declared.

  
    The following example illustrates the effect of using a deferred foreign
    key constraint.

-- Database schema. Both tables are initially empty. 
CREATE TABLE artist(
  artistid    INTEGER PRIMARY KEY, 
  artistname  TEXT
);
CREATE TABLE track(
  trackid     INTEGER,
  trackname   TEXT, 
  trackartist INTEGER REFERENCES artist(artistid) DEFERRABLE INITIALLY DEFERRED
);

sqlite3&gt; -- If the foreign key constraint were immediate, this INSERT would
sqlite3&gt; -- cause an error (since as there is no row in table artist with
sqlite3&gt; -- artistid=5). But as the constraint is deferred and there is an
sqlite3&gt; -- open transaction, no error occurs.
sqlite3&gt; BEGIN;
sqlite3&gt;   INSERT INTO track VALUES(1, 'White Christmas', 5);

sqlite3&gt; -- The following COMMIT fails, as the database is in a state that
sqlite3&gt; -- does not satisfy the deferred foreign key constraint. The
sqlite3&gt; -- transaction remains open.
sqlite3&gt; COMMIT;
SQL error: foreign key constraint failed

sqlite3&gt; -- After inserting a row into the artist table with artistid=5, the
sqlite3&gt; -- deferred foreign key constraint is satisfied. It is then possible
sqlite3&gt; -- to commit the transaction without error.
sqlite3&gt;   INSERT INTO artist VALUES(5, 'Bing Crosby');
sqlite3&gt; COMMIT;

  
    A nested savepoint transaction may be RELEASEd while the
    database is in a state that does not satisfy a deferred foreign key 
    constraint. A transaction savepoint (a non-nested savepoint that was
    opened while there was not currently an open transaction), on the 
    other hand, is subject to the same restrictions as a COMMIT - attempting 
    to RELEASE it while the database is in such a state will fail.

  
    If a COMMIT statement (or the RELEASE of a transaction SAVEPOINT) fails
    because the database is currently in a state that violates a deferred
    foreign key constraint and there are currently
    nested savepoints, the nested savepoints remain open.


c2: SQLite Foreign Key Support
c3: 4.3. ON DELETE and ON UPDATE Actions
c5: foreignkeys.html#fk_actions
c4:
Foreign key ON DELETE and ON UPDATE clauses are used to configure actions
    that take place when deleting rows from the parent table (ON DELETE), or 
    modifying the parent key values of existing rows (ON UPDATE). A single
    foreign key constraint may have different actions configured for ON DELETE
    and ON UPDATE. Foreign key actions are similar to triggers in many ways.

  
    The ON DELETE and ON UPDATE action associated with each foreign key in an
    SQLite database is one of "NO ACTION", "RESTRICT", "SET NULL",
    "SET DEFAULT" or "CASCADE". If an action is not explicitly specified, it 
    defaults to "NO ACTION".

  
     NO ACTION: Configuring "NO ACTION" means just that: when a
     parent key is modified or deleted from the database, no special action is
     taken.

     RESTRICT: The "RESTRICT" action means that the application
      is prohibited from deleting (for ON DELETE RESTRICT) or modifying
      (for ON UPDATE RESTRICT) a parent key when there exists one or more child
      keys mapped to it. The difference between the effect of a RESTRICT
      action and normal foreign key constraint enforcement is that the
      RESTRICT action processing happens as soon as the field is updated -
      not at the end of the current statement as it would with an immediate
      constraint, or at the end of the current transaction as it would with
      a deferred constraint.
      Even if the foreign key constraint it is 
      attached to is deferred, configuring a RESTRICT action causes SQLite to 
      return an error immediately if a parent key with dependent child keys is 
      deleted or modified.

     SET NULL: If the configured action is "SET NULL", then when
      a parent key is deleted (for ON DELETE SET NULL) or modified (for ON 
      UPDATE SET NULL), the child key columns of all rows in the child table
      that mapped to the parent key are set to contain SQL NULL values.

     SET DEFAULT: The "SET DEFAULT" actions are similar to
      "SET NULL",
      except that each of the child key columns is set to contain the column's 
      default value instead of NULL. Refer to the CREATE TABLE 
      documentation for details on how default values are assigned to table
      columns.

     CASCADE: A "CASCADE" action propagates the delete or update
      operation on the parent key to each dependent child key. For an "ON 
      DELETE CASCADE" action, this means that each row in the child table that
      was associated with the deleted parent row is also deleted. For an "ON
      UPDATE CASCADE" action, it means that the values stored in each dependent
      child key are modified to match the new parent key values.
  

  
    For example, adding an "ON UPDATE CASCADE" clause to the foreign key as
    shown below enhances the example schema from section 1 to allow the user
    to update the artistid (the parent key of the foreign key constraint) 
    column without breaking referential integrity:
-- Database schema
CREATE TABLE artist(
  artistid    INTEGER PRIMARY KEY, 
  artistname  TEXT
);
CREATE TABLE track(
  trackid     INTEGER,
  trackname   TEXT, 
  trackartist INTEGER REFERENCES artist(artistid) ON UPDATE CASCADE
);

sqlite&gt; SELECT * FROM artist;
artistid  artistname       
--------  -----------------
1         Dean Martin      
2         Frank Sinatra    

sqlite&gt; SELECT * FROM track;
trackid  trackname          trackartist
-------  -----------------  -----------
11       That's Amore       1
12       Christmas Blues    1
13       My Way             2  

sqlite&gt; -- Update the artistid column of the artist record for "Dean Martin".
sqlite&gt; -- Normally, this would raise a constraint, as it would orphan the two
sqlite&gt; -- dependent records in the track table. However, the ON UPDATE CASCADE clause
sqlite&gt; -- attached to the foreign key definition causes the update to "cascade"
sqlite&gt; -- to the child table, preventing the foreign key constraint violation.
sqlite&gt; UPDATE artist SET artistid = 100 WHERE artistname = 'Dean Martin';

sqlite&gt; SELECT * FROM artist;
artistid  artistname       
--------  -----------------
2         Frank Sinatra    
100       Dean Martin      

sqlite&gt; SELECT * FROM track;
trackid  trackname          trackartist
-------  -----------------  -----------
11       That's Amore       100
12       Christmas Blues    100  
13       My Way             2  


  
    Configuring an ON UPDATE or ON DELETE action does not mean that the foreign
    key constraint does not need to be satisfied. For example, if an
    "ON DELETE SET DEFAULT" action is configured,
    but there is no row in the parent table 
    that corresponds to the default values of the child key columns, deleting
    a parent key while dependent child keys exist still causes a foreign key
    violation. For example:

-- Database schema
CREATE TABLE artist(
  artistid    INTEGER PRIMARY KEY, 
  artistname  TEXT
);
CREATE TABLE track(
  trackid     INTEGER,
  trackname   TEXT, 
  trackartist INTEGER DEFAULT 0 REFERENCES artist(artistid) ON DELETE SET DEFAULT
);

sqlite&gt; SELECT * FROM artist;
artistid  artistname       
--------  -----------------
3         Sammy Davis Jr.

sqlite&gt; SELECT * FROM track;
trackid  trackname          trackartist
-------  -----------------  -----------
14       Mr. Bojangles      3

sqlite&gt; -- Deleting the row from the parent table causes the child key
sqlite&gt; -- value of the dependent row to be set to integer value 0. However, this
sqlite&gt; -- value does not correspond to any row in the parent table. Therefore
sqlite&gt; -- the foreign key constraint is violated and an is exception thrown.
sqlite&gt; DELETE FROM artist WHERE artistname = 'Sammy Davis Jr.';
SQL error: foreign key constraint failed

sqlite&gt; -- This time, the value 0 does correspond to a parent table row. And
sqlite&gt; -- so the DELETE statement does not violate the foreign key constraint
sqlite&gt; -- and no exception is thrown.
sqlite&gt; INSERT INTO artist VALUES(0, 'Unknown Artist');
sqlite&gt; DELETE FROM artist WHERE artistname = 'Sammy Davis Jr.';

sqlite&gt; SELECT * FROM artist;
artistid  artistname       
--------  -----------------
0         Unknown Artist

sqlite&gt; SELECT * FROM track;
trackid  trackname          trackartist
-------  -----------------  -----------
14       Mr. Bojangles      0


  
    Those familiar with SQLite triggers
    will have noticed that the 
    "ON DELETE SET DEFAULT" action demonstrated in the example above is
    similar in effect to the following AFTER DELETE trigger:
CREATE TRIGGER on_delete_set_default AFTER DELETE ON artist BEGIN
  UPDATE child SET trackartist = 0 WHERE trackartist = old.artistid;
END;


  
    Whenever a row in the parent table of a foreign key constraint is deleted,
    or when the values stored in the parent key column or columns are modified, 
    the logical sequence of events is:

  
    Execute applicable BEFORE trigger programs,
    Check local (non foreign key) constraints,
    Update or delete the row in the parent table,
    Perform any required foreign key actions,
    Execute applicable AFTER trigger programs.
  

  
    There is one important difference between ON UPDATE foreign key actions and
    SQL triggers. An ON UPDATE action is only taken if the values of the
    parent key are modified so that the new parent key values are 
    not equal to the old. For example:

-- Database schema
CREATE TABLE parent(x PRIMARY KEY);
CREATE TABLE child(y REFERENCES parent ON UPDATE SET NULL);

sqlite&gt; SELECT * FROM parent;
x
----
key

sqlite&gt; SELECT * FROM child;
y
----
key

sqlite&gt; -- Since the following UPDATE statement does not actually modify
sqlite&gt; -- the parent key value, the ON UPDATE action is not performed and
sqlite&gt; -- the child key value is not set to NULL.
sqlite&gt; UPDATE parent SET x = 'key';
sqlite&gt; SELECT IFNULL(y, 'null') FROM child;
y
----
key

sqlite&gt; -- This time, since the UPDATE statement does modify the parent key
sqlite&gt; -- value, the ON UPDATE action is performed and the child key is set
sqlite&gt; -- to NULL.
sqlite&gt; UPDATE parent SET x = 'key2';
sqlite&gt; SELECT IFNULL(y, 'null') FROM child;
y
----
null


c2: SQLite Foreign Key Support
c3: 5. CREATE, ALTER and DROP TABLE commands
c5: foreignkeys.html#fk_schemacommands
c4:
This section describes the way the CREATE TABLE, ALTER TABLE,
    and DROP TABLE commands
    interact with SQLite's foreign keys.

  
    A CREATE TABLE command operates the same whether or not
    foreign key constraints are enabled.  The parent key definitions of 
    foreign key constraints are not checked when a table is created. There is
    nothing stopping the user from creating a foreign key definition that
    refers to a parent table that does not exist, or to parent key columns that
    do not exist or are not collectively bound by a PRIMARY KEY or UNIQUE
    constraint.

  
    The ALTER TABLE command works differently in two respects when foreign
    key constraints are enabled:

  
     
         It is not possible to use the "ALTER TABLE ... ADD COLUMN" syntax
         to add a column that includes a REFERENCES clause, unless the default
         value of the new column is NULL. Attempting to do so returns an
         error.

     
         If an "ALTER TABLE ... RENAME TO" command is used to rename a table
         that is the parent table of one or more foreign key constraints, the
         definitions of the foreign key constraints are modified to refer to
         the parent table by its new name. The text of the child CREATE
         TABLE statement or statements stored in the sqlite_schema table are 
         modified to reflect the new parent table name.
  

  
    If foreign key constraints are enabled when it is prepared, the 
    DROP TABLE command performs an implicit DELETE to remove all
    rows from the table before dropping it. The implicit DELETE does not cause
    any SQL triggers to fire, but may invoke foreign key actions or constraint
    violations. If an immediate foreign key constraint is violated, the DROP
    TABLE statement fails and the table is not dropped. If a deferred foreign
    key constraint is violated, then an error is reported when the user attempts
    to commit the transaction if the foreign key constraint violations still
    exist at that point. Any "foreign key mismatch" errors encountered as part 
    of an implicit DELETE are ignored.

  
    The intent of these enhancements to the ALTER TABLE and DROP TABLE
    commands is to ensure that they cannot be used to create a database that
    contains foreign key violations, at least while foreign key constraints are
    enabled. There is one exception to this rule though. If a parent key is
    not subject to a PRIMARY KEY or UNIQUE constraint created as part of the
    parent table definition, but is subject to a UNIQUE constraint by virtue
    of an index created using the CREATE INDEX command, then the child 
    table may be populated without causing a "foreign key mismatch" error. If
    the UNIQUE index is dropped from the database schema, then the parent table
    itself is dropped, no error will be reported. However the database may be
    left in a state where the child table of the foreign key constraint contains
    rows that do not refer to any parent table row. This case can be avoided
    if all parent keys in the database schema are constrained by PRIMARY KEY
    or UNIQUE constraints added as part of the parent table definition, not
    by external UNIQUE indexes.

  
    The properties of the DROP TABLE and ALTER TABLE commands described
    above only apply if foreign keys are enabled. If the user considers them
    undesirable, then the workaround is to use PRAGMA foreign_keys to 
    disable foreign key constraints before executing the DROP or ALTER TABLE 
    command. Of course, while foreign key constraints are disabled, there is nothing
    to stop the user from violating foreign key constraints and thus creating
    an internally inconsistent database.


c2: SQLite Foreign Key Support
c3: 6. Limits and Unsupported Features
c5: foreignkeys.html#fk_unsupported
c4:
This section lists a few limitations and omitted features that are not
    mentioned elsewhere.

  
     
      No support for the MATCH clause. According to SQL92, a MATCH clause
         may be attached to a composite foreign key definition to modify the way
         NULL values that occur in child keys are handled. If "MATCH SIMPLE" is
         specified, then a child key is not required to correspond to any row
         of the parent table if one or more of the child key values are NULL.
         If "MATCH FULL" is specified, then if any of the child key values is
         NULL, no corresponding row in the parent table is required, but all
         child key values must be NULL. Finally, if the foreign key constraint
         is declared as "MATCH PARTIAL" and one of the child key values is NULL,
         there must exist at least one row in the parent table for which the
         non-NULL child key values match the parent key values.

       
         SQLite parses MATCH clauses (i.e. does not report a syntax error
         if you specify one), but does not enforce them. All foreign key 
         constraints in SQLite are handled as if MATCH SIMPLE were specified.
     
      No support for switching constraints between deferred and immediate 
         mode. Many systems allow the user to toggle individual foreign key
         constraints between deferred and immediate 
         mode at runtime (for example using the Oracle "SET CONSTRAINT" command).
         SQLite does not support this. In SQLite, a foreign key constraint is
         permanently marked as deferred or immediate when it is created.

    
      Recursion limit on foreign key actions. The 
         SQLITE_MAX_TRIGGER_DEPTH and SQLITE_LIMIT_TRIGGER_DEPTH
         settings determine the maximum allowable depth of trigger
         program recursion. For the purposes of these limits,
         foreign key actions are considered trigger programs. The
         PRAGMA recursive_triggers setting does not affect the operation 
         of foreign key actions. It is not possible to disable recursive foreign 
         key actions.
   
This page last modified on  2022-01-20 21:38:08 UTC


c2: Pointer Passing Interfaces
c3: 1. Overview
c5: bindptr.html#overview
c4:
Three new "_pointer()" interfaces were added to SQLite 3.20.0 (2017-08-01):

 sqlite3_bind_pointer(),
 sqlite3_result_pointer(), and
 sqlite3_value_pointer().


Questions and confusion quickly arose
on the mailing lists about the purpose behind these new interfaces,
why they were introduced, and what problem they solve.  This essay attempts
to answer those questions and clear up the confusion.


c2: Pointer Passing Interfaces
c3: 2. A Brief History Of Pointer Passing In SQLite
c5: bindptr.html#a_brief_history_of_pointer_passing_in_sqlite
c4:
It is sometimes convenient for SQLite extensions to
communicate non-SQL values between subcomponents or between the extension
and the application.  Some examples:



In the FTS3 extension, the 
MATCH operator (which does the full-text search)
needs to communicate details of matching entries 
to the snippet(), offsets(),
and matchinfo() functions so that those functions can convert the details
of the match into useful output.


In order for an application to 
add new extensions to FTS5, such as new tokenizers, 
the application needs a pointer to the "fts5_api" object.


In the CARRAY extension, the application needs to tell the 
extension the
location of a C-language array that contains the data for the table-valued
function that the extension implements.



The traditional way of communicating this information was to transform a
C-language pointer into a BLOB or a 64-bit integer, then move that BLOB or
integer through SQLite using the usual interfaces like
sqlite3_bind_blob(), sqlite3_result_blob(), sqlite3_value_blob() or
the integer equivalents.


c2: Pointer Passing Interfaces
c3: 2.1. Upping The Threat Level
c5: bindptr.html#upping_the_threat_level
c4:
Passing around pointers as if they were integers or BLOBs is easy,
effective, and works well in an environment where the application
components are all friendly toward one another.  However, passing pointers
as integers and BLOBs allows hostile SQL text to forge invalid pointers that
can carry out mischief.


For example, the first argument to the snippet() function is supposed to
be a special column of the FTS3 table that contains a pointer to an fts3cursor
object that contains information about the current full text search match.
That pointer was formerly passed as a BLOB.  
For example, if the FTS3 table is named "t1" and has a column named "cx",
one might write:

SELECT snippet(t1) FROM t1 WHERE cx MATCH $pattern;



But if a hacker is able to run arbitrary SQL, he might run a slightly
different query, like this:

SELECT hex(t1) FROM t1 WHERE cx MATCH $pattern;



Because the pointer is passed in the t1 column of the t1
table as a BLOB (in older versions of SQLite), such a query would have 
shown the value of the
pointer in hex.  The attacker could then modify that pointer to try to
get the snippet() function to modify memory in some other part of 
the application address space instead of the fts3cursor object it 
was supposed to be operating on:

SELECT snippet(x'6092310100000000') FROM t1 WHERE cx MATCH $pattern;



Historically, this was not considered a threat.  The argument was that if
a hostile agent is able to inject arbitrary SQL text into the application,
then that agent is already in full control of the application, so
letting the hostile agent forge a pointer does not give the agent
any new capability.


For most cases, it is true that potential attackers have no way of injecting
arbitrary SQL, and so most uses of SQLite are immune to the attack above.
But there are some notable exceptions.  To wit:



The WebSQL interface
to webkit allowed any webpage to run arbitrary SQL in the browser
for Chrome and Safari.  That arbitrary SQL was supposed to be run inside
a sandbox where it could do no harm even if exploited, but that sandbox
turned out to be less secure than people supposed.  In the spring of 2017, 
one team of hackers was able to root an iMac using a long sequence of 
exploits, one of which involved corrupting the pointers passed as BLOB 
values to the snippet() FTS3 function of an SQLite database running via
the WebSQL interface inside of Safari.


On Android, we are told, there are many services that will blindly 
run arbitrary SQL that is passed to them by untrustworthy apps
that have been downloaded from dodgy corners of the internet.
Android services are suppose to be more guarded about running SQL
from unvetted sources.  This author does not have any specific examples
to the contrary, but he has heard rumors that they exist.  Even if
all Android services are more careful and properly vet all the SQL
they run, it would be difficult to audit them
all in order to verify that they are safe.  Hence, security-minded people
are keen to ensure that no exploits are possible by passing arbitrary
SQL text.


The Fossil version control system (designed
and written for the purpose of supporting SQLite development) allows
mildly trusted users to enter arbitrary SQL for generating trouble-ticket
reports.  That SQL is sanitized using the
sqlite3_set_authorizer() interface, and no exploits have ever been
found.  But this is an example of potentially hostile agents being able to
inject arbitrary SQL into the system.


c2: Pointer Passing Interfaces
c3: 2.2. Preventing Forged Pointers
c5: bindptr.html#preventing_forged_pointers
c4:
The first attempt at closing security gaps in pointer passing was to
prevent pointer values from being forged.  This was accomplished by
having the sender attach a subtype to each pointer using
sqlite3_result_subtype() and having the receiver verify that subtype
using sqlite3_value_subtype() and reject pointers that had an incorrect
subtype.  Since there is no way to attach a subtype to a result using
pure SQL, this prevents pointers from being forged using SQL.  The only
way to send a pointer is to use C code.  If an attacker can set a subtype,
then he is also able to forge a pointer without the help of SQLite.


Using subtypes to identify valid pointers prevented the WebSQL exploit.
But it turned out to be an incomplete solution.


c2: Pointer Passing Interfaces
c3: 2.3. Pointer Leaks
c5: bindptr.html#pointer_leaks
c4:
The use of subtypes on pointers prevented pointer forgery using
pure SQL.  But subtypes do nothing to prevent an attacker from reading
the values of pointers.  In other words, subtypes on pointer values
prevent attacks using SQL statements like this:

SELECT snippet(x'6092310100000000') FROM t1 WHERE cx MATCH $pattern;



The BLOB argument to snippet() does not have the correct subtype, so the
snippet function ignores it, makes no changes to any data structures,
and harmlessly returns NULL.


But the use of subtypes does nothing to prevent the value of a
pointer from being read using SQL code like this:

SELECT hex(t1) FROM t1 WHERE cx MATCH $pattern;



What harm could come of that, you ask?  The SQLite developers (including
this author) wondered the same thing.  But then security researchers
pointed out that knowledge of pointers can help attackers to circumvent
address-space randomization defenses.  This is called a "pointer leak".
A pointer leak is not itself a vulnerability, but it can aid an attacker
in effectively exploiting other vulnerabilities.


c2: Pointer Passing Interfaces
c3: 3. The New Pointer-Passing Interfaces
c5: bindptr.html#the_new_pointer_passing_interfaces
c4:
Allowing extension components to pass private information to one another
securely and without introducing pointer leaks requires new interfaces:


sqlite3_bind_pointer(S,I,P,T,D) &rarr;
Bind pointer P of type T to the I-th parameter of prepared statement S.
D is an optional destructor function for P.
sqlite3_result_pointer(C,P,T,D) &rarr;
Return pointer P of type T as the argument of function C.
D is an optional destructor function for P.
sqlite3_value_pointer(V,T) &rarr;
Return the pointer of type T associated with value V, or if V has no
associated pointer, or if the pointer on V is of a type different from
T, then return NULL.



To SQL, the values created by sqlite3_bind_pointer() and 
sqlite3_result_pointer() are indistinguishable from NULL.  An
SQL statement that tries to use the hex() function to read the
value of a pointer will get an SQL NULL answer.  The only way to
discover whether or not a value has an associated pointer is to
use the sqlite3_value_pointer() interface with the appropriate
type string T. 


Pointer values read by sqlite3_value_pointer()
cannot be generated by pure SQL.  Hence, it is not possible for SQL to
forge pointers.


Pointer values generated by sqlite3_bind_pointer() and
sqlite3_result_pointer() cannot be read by pure SQL.
Hence, it is not possible for SQL to leak the value of pointers.


In this way the new pointer-passing interface seems to solve all of the
security problems associated with passing pointer values from one
extension to another in SQLite.


c2: Pointer Passing Interfaces
c3: 3.1. Pointer Types
c5: bindptr.html#pointer_types
c4:
The "pointer type" in the last parameter to sqlite3_bind_pointer(),
sqlite3_result_pointer(), and sqlite3_value_pointer() is used to prevent
pointers intended for one extension from being redirected to a different
extension.  For example, without the use of pointer types, an attacker 
could still get access to pointer information in a system that included 
both the FTS3 and the CARRAY extension using SQL like this:

SELECT ca.value FROM t1, carray(t1,10) AS ca WHERE cx MATCH $pattern



In the statement above, the FTS3 cursor pointer generated by the
MATCH operator is send into the carray() table-valued function instead
of its intended recipient snippet().  The carray() function treats the
pointer as a pointer to an array of integers and returns each integer
one by one, thus leaking the content of the FTS3 cursor object.  Since
the FTS3 cursor object contains pointers to other objects, the statement
above would be a pointer leak.


Except, the statement above does not work, thanks to pointer types.
The pointer generated by the MATCH operator has a type of "fts3cursor"
but the carray() function expects to receives a pointer of type "carray".
Because the pointer type on the sqlite3_result_pointer() does not match
the pointer type on the sqlite3_value_pointer() call, 
sqlite3_value_pointer() returns NULL in carray() and thus signals
the CARRAY extension that it has been passed an invalid pointer.


c2: Pointer Passing Interfaces
c3: 3.1.1. Pointer types are static strings
c5: bindptr.html#pointer_types_are_static_strings
c4:
Pointer types are static strings, which ideally should be string literals
embedded directly in the SQLite API call, not parameters passed in from
other functions.  Consideration was given to using integer values as
the pointer type, but static strings provides a much larger name space
which reduces the chance of accidental type-name collisions between
unrelated extensions.


By "static string", we mean a zero-terminated array of bytes that is
fixed and unchanging for the life of the program.  In other words, the
pointer type string should be a string constant.
In contrast, a "dynamic string" is a zero-terminated array of bytes
that is held in memory allocated
from the heap, and which must be freed to avoid a memory leak.
Do not use dynamic strings as the pointer type string.


Multiple commentators have expressed a desire to use dynamic strings
for the pointer type, and to have SQLite take ownership of the type strings
and to automatically free the type string
when it has finished using it.  That design is rejected for the
following reasons:



The pointer type is not intended to be flexible and dynamic.  The
pointer type is intended to be a design-time constant.  Applications
should not synthesize pointer type strings at run-time.  Providing
support for dynamic pointer type strings would lead developers
to misuse the pointer-passing interfaces by creating run-time
synthesized pointer type strings.  Requiring the pointer type strings
to be static encourages developers to do the right thing by choosing
fixed pointer type names at design-time and encoding those names
as constant strings.


All string values at the SQL level in SQLite are dynamic strings.  
Requiring type strings to be static makes it difficult to 
create an application-defined SQL function that
can synthesize a pointer of an arbitrary type.  We do not want users
to create such SQL functions, since such functions would compromise the
security of the system.  Thus, the requirement to use static strings
helps to defend that the integrity of the pointer-passing interfaces against
ill-designed SQL functions.  The static string requirement is not
a perfect defense, since a sophisticated programmer can code around
it, and a novice program can simply take the memory leak.  But by
stating that the pointer type string must be static, we hope to encourage
developers who might otherwise use a dynamic string for the pointer type
to think more carefully about the problem and avoid introducing
security issues.


Having SQLite take ownership of the type strings would impose a performance
cost on all applications, even applications that do not use the 
pointer-passing interfaces.  SQLite passes values around as instances
of the sqlite3_value object.  That object has a destructor, which because
of the fact that sqlite3_value objects are used for nearly everything, is
invoked frequently.  If the destructor needs to check to see if there is
a pointer type string that needs to be freed, that is a few extra CPU
cycles that need to be burned on each call to the destructor.  Those
cycles add up.  We would be willing to bear the cost of the extra CPU
cycles if pointer-passing was a commonly used programming paradigm, but
pointer-passing is rare, and so it seems unwise to impose a run-time cost
on billions and billions of applications that do not use pointer passing
just for convenience of a few applications that do.



If you feel that you need dynamic pointer type strings in your application,
that is a strong indicator that you are misusing the pointer-passing interface.
Your intended use may be unsafe.
Please rethink your design.  Determine if you really need to be passing
pointers through SQL in the first place.  Or perhaps find a different
mechanism other than the pointer-passing interfaces described by this
article.


c2: Pointer Passing Interfaces
c3: 3.2. Destructor Functions
c5: bindptr.html#destructor_functions
c4:
The last parameter to the sqlite3_bind_pointer() and
sqlite3_result_pointer() routines is a pointer to a procedure
used to dispose of the P pointer once SQLite has finished with it.
This pointer can be NULL, in which case no destructor is called.


When the D parameter is not NULL, that means that ownership of the
pointer is being transferred to SQLite.  SQLite will take responsibility
for freeing resources associated with the pointer when it has finished
using the pointer.  If the D parameter is NULL, that means that ownership
of the pointer remains with the caller and the caller is responsible for
disposing of the pointer.


Note that the destructor function D is for the pointer value P, not for
the type string T.  The type string T should be a static string with an
infinite lifetime.


If ownership of the pointer is passed into SQLite by providing a
non-NULL D parameter to sqlite3_bind_pointer() or sqlite3_result_pointer()
then the ownership remains with SQLite until the object is destroyed.
There is no way to transfer ownership out of SQLite and back into the
application again.


c2: Pointer Passing Interfaces
c3: 4. Restrictions On The Use of Pointer Values
c5: bindptr.html#restrictions_on_the_use_of_pointer_values
c4:
The pointers that piggy-back on SQL NULL values using the
sqlite3_bind_pointer(), sqlite3_result_pointer(), and
sqlite3_value_pointer() interface are transient and ephemeral.
The pointers are never written into the database.  The pointers
will not survive sorting.  The latter fact is why there is no
sqlite3_column_pointer() interface, since it is impossible to
predict whether or not the query planner will insert a sort operation
prior to returning a value from a query, so it would be impossible to
know if a pointer value inserted into a query by
sqlite3_bind_pointer() or sqlite3_result_pointer() would survive
through to the result set.


Pointer values must flow directly from their producer into their
consumer, with no intermediate operators or functions.  Any transformation
of a pointer value destroys the pointer and transforms the value into
an ordinary SQL NULL.


c2: Pointer Passing Interfaces
c3: 5. Summary
c5: bindptr.html#summary
c4:
Key take-aways from this essay:



The internet is an increasingly hostile place.  These day, developers
should assume that attackers will find a way to execute arbitrary SQL 
in an application.
Applications should be designed to prevent the execution of arbitrary
SQL from escalating into a more severe exploit.


A few SQLite extensions benefit from passing pointers:

The FTS3 MATCH operator passes pointers into snippet(),
    offsets(), and matchinfo().
The carray table-valued function needs to accept a pointer to
    an array of C-language values from the application.
The remember() extension
    needs a pointer to a C-language integer variable in which to remember
    the value it passes.
Applications need to receive a pointer to the "fts5_api" object in order
    to add extensions, such as custom tokenizers, to the FTS5 extension.



Pointers should never be exchanged by encoding them as some other
SQL datatype, such as integers or BLOBs.  Instead, use the interfaces
designed to facilitate secure pointer passing:
sqlite3_bind_pointer(), sqlite3_result_pointer(), and
sqlite3_value_pointer().


The use of pointer-passing is an advanced technique that should be used
infrequently and cautiously.  Pointer-passing should not be
used haphazardly or carelessly.  Pointer-passing is a sharp tool 
that can leave deep scars if misused.


The "pointer type" string which is the last parameter to each of the
pointer-passing interfaces should be a distinct, application-specific
string literal that appears directly in the API call.  The pointer type
should not be a parameter passed in from a higher-level function.

This page last modified on  2022-10-07 10:23:26 UTC


c2: The SQLite Query Optimizer Overview
c3: 1. Introduction
c5: optoverview.html#introduction
c4:
This document provides an overview of how the query planner and optimizer
  for SQLite works.



  Given a single SQL statement, there might be dozens, hundreds, or even
  thousands of ways to implement that statement, depending on the complexity
  of the statement itself and of the underlying database schema.  The 
  task of the query planner is to select the algorithm that minimizes
  disk I/O and CPU overhead.



  Additional background information is available in the
  indexing tutorial document.



  With release 3.8.0 (2013-08-26),
  the SQLite query planner was reimplemented as the
  Next Generation Query Planner or "NGQP".  All of the features, techniques,
  and algorithms described in this document are applicable to both the
  pre-3.8.0 legacy query planner and to the NGQP.  For further information on
  how the NGQP differs from the legacy query planner, see the 
  detailed description of the NGQP.


c2: The SQLite Query Optimizer Overview
c3: 2. WHERE Clause Analysis
c5: optoverview.html#where_clause_analysis
c4:
The WHERE clause on a query is broken up into "terms" where each term
  is separated from the others by an AND operator.
  If the WHERE clause is composed of constraints separated by the OR
  operator then the entire clause is considered to be a single "term"
  to which the OR-clause optimization is applied.


  All terms of the WHERE clause are analyzed to see if they can be
  satisfied using indexes.
  To be usable by an index a term must usually be of one of the following
  forms:


  column = expression
  column IS expression
  column &gt; expression
  column &gt;= expression
  column &lt; expression
  column &lt;= expression
  expression = column
  expression &gt; column
  expression &gt;= column
  expression &lt; column
  expression &lt;= column
  column IN (expression-list)
  column IN (subquery)
  column IS NULL
  column LIKE pattern
  column GLOB pattern



  If an index is created using a statement like this:

CREATE INDEX idx_ex1 ON ex1(a,b,c,d,e,...,y,z);



  Then the index might be used if the initial columns of the index
  (columns a, b, and so forth) appear in WHERE clause terms.
  The initial columns of the index must be used with
  the = or IN or IS operators.  
  The right-most column that is used can employ inequalities.  
  For the right-most
  column of an index that is used, there can be up to two inequalities
  that must sandwich the allowed values of the column between two extremes.


  It is not necessary for every column of an index to appear in a
  WHERE clause term in order for that index to be used. 
  However, there cannot be gaps in the columns of the index that are used.
  Thus for the example index above, if there is no WHERE clause term
  that constrains column c, then terms that constrain columns a and b can
  be used with the index but not terms that constrain columns d through z.
  Similarly, index columns will not normally be used (for indexing purposes)
  if they are to the right of a 
  column that is constrained only by inequalities.
  (See the skip-scan optimization below for the exception.)


  In the case of indexes on expressions, whenever the word "column" is
  used in the foregoing text, one can substitute "indexed expression"
  (meaning a copy of the expression that appears in the CREATE INDEX
  statement) and everything will work the same.


c2: The SQLite Query Optimizer Overview
c3: 2.1. Index Term Usage Examples
c5: optoverview.html#index_term_usage_examples
c4:
For the index above and WHERE clause like this:

... WHERE a=5 AND b IN (1,2,3) AND c IS NULL AND d='hello'


  The first four columns a, b, c, and d of the index would be usable since
  those four columns form a prefix of the index and are all bound by
  equality constraints.


  For the index above and WHERE clause like this:

... WHERE a=5 AND b IN (1,2,3) AND c>12 AND d='hello'


  Only columns a, b, and c of the index would be usable.  The d column
  would not be usable because it occurs to the right of c and c is
  constrained only by inequalities.


  For the index above and WHERE clause like this:

... WHERE a=5 AND b IN (1,2,3) AND d='hello'


  Only columns a and b of the index would be usable.  The d column
  would not be usable because column c is not constrained and there can
  be no gaps in the set of columns that usable by the index.


  For the index above and WHERE clause like this:

... WHERE b IN (1,2,3) AND c NOT NULL AND d='hello'


  The index is not usable at all because the left-most column of the
  index (column "a") is not constrained.  Assuming there are no other
  indexes, the query above would result in a full table scan.


  For the index above and WHERE clause like this:

... WHERE a=5 OR b IN (1,2,3) OR c NOT NULL OR d='hello'


  The index is not usable because the WHERE clause terms are connected
  by OR instead of AND. This query would result in a full table scan.
  However, if three additional indexes where added that contained columns
  b, c, and d as their left-most columns, then the
  OR-clause optimization might apply.


c2: The SQLite Query Optimizer Overview
c3: 3. The BETWEEN Optimization
c5: optoverview.html#the_between_optimization
c4:
If a term of the WHERE clause is of the following form:


  expr1 BETWEEN expr2 AND expr3


  Then two "virtual" terms are added as follows:


  expr1 &gt;= expr2 AND expr1 &lt;= expr3


  Virtual terms are used for analysis only and do not cause any byte-code
  to be generated.
  If both virtual terms end up being used as constraints on an index,
  then the original BETWEEN term is omitted and the corresponding test
  is not performed on input rows.
  Thus if the BETWEEN term ends up being used as an index constraint
  no tests are ever performed on that term.
  On the other hand, the
  virtual terms themselves never causes tests to be performed on
  input rows.
  Thus if the BETWEEN term is not used as an index constraint and
  instead must be used to test input rows, the expr1 expression is
  only evaluated once.


c2: The SQLite Query Optimizer Overview
c3: 4. OR Optimizations
c5: optoverview.html#or_optimizations
c4:
WHERE clause constraints that are connected by OR instead of AND can
  be handled in two different ways.
  If a term consists of multiple subterms containing a common column
  name and separated by OR, like this:


  column = expr1 OR column = expr2 OR column = expr3 OR ...


  Then that term is rewritten as follows:


  column IN (expr1,expr2,expr3,...)


  The rewritten term then might go on to constrain an index using the
  normal rules for IN operators.  Note that column must be
  the same column in every OR-connected subterm,
  although the column can occur on either the left or the right side of
  the = operator.


  If and only if the previously described conversion of OR to an IN operator
  does not work, the second OR-clause optimization is attempted.
  Suppose the OR clause consists of multiple subterms as follows:


  expr1 OR expr2 OR expr3


  Individual subterms might be a single comparison expression like
  a=5 or x&gt;y or they can be 
  LIKE or BETWEEN expressions, or a subterm
  can be a parenthesized list of AND-connected sub-subterms.
  Each subterm is analyzed as if it were itself the entire WHERE clause
  in order to see if the subterm is indexable by itself.
  If every subterm of an OR clause is separately indexable
  then the OR clause might be coded such that a separate index is used
  to evaluate each term of the OR clause.  One way to think about how
  SQLite uses separate indexes for each OR clause term is to imagine
  that the WHERE clause where rewritten as follows:


  rowid IN (SELECT rowid FROM table WHERE expr1
            UNION SELECT rowid FROM table WHERE expr2
            UNION SELECT rowid FROM table WHERE expr3)


  The rewritten expression above is conceptual; WHERE clauses containing
  OR are not really rewritten this way.
  The actual implementation of the OR clause uses a mechanism that is
  more efficient and that works even for WITHOUT ROWID tables or 
  tables in which the "rowid" is inaccessible.  Nevertheless,
  the essence of the implementation is captured by the statement
  above:  Separate indexes are used to find candidate result rows
  from each OR clause term and the final result is the union of
  those rows.


  Note that in most cases, SQLite will only use a single index for each
  table in the FROM clause of a query.  The second OR-clause optimization
  described here is the exception to that rule.  With an OR-clause,
  a different index might be used for each subterm in the OR-clause.


  For any given query, the fact that the OR-clause optimization described
  here can be used does not guarantee that it will be used.
  SQLite uses a cost-based query planner that estimates the CPU and
  disk I/O costs of various competing query plans and chooses the plan
  that it thinks will be the fastest.  If there are many OR terms in
  the WHERE clause or if some of the indexes on individual OR-clause 
  subterms are not very selective, then SQLite might decide that it is
  faster to use a different query algorithm, or even a full-table scan.
  Application developers can use the
  EXPLAIN QUERY PLAN prefix on a statement to get a
  high-level overview of the chosen query strategy.


c2: The SQLite Query Optimizer Overview
c3: 5. The LIKE Optimization
c5: optoverview.html#the_like_optimization
c4:
A WHERE-clause term that uses the LIKE or GLOB operator
  can sometimes be used with an index to do a range search, 
  almost as if the LIKE or GLOB were an alternative to a BETWEEN
  operator.
  There are many conditions on this optimization:


  
  The right-hand side of the LIKE or GLOB must be either a string literal
      or a parameter bound to a string literal
      that does not begin with a wildcard character.
  It must not be possible to make the LIKE or GLOB operator true by
      having a numeric value (instead of a string or blob) on the
      left-hand side. This means that either:
      
       the left-hand side of the LIKE or GLOB operator is the name
           of an indexed column with TEXT affinity, or
       the right-hand side pattern argument does not begin with a
           minus sign ("-") or a digit.
      
      This constraint arises from the fact that numbers do not sort in
      lexicographical order.  For example: 9&lt;10 but '9'&gt;'10'.
  The built-in functions used to implement LIKE and GLOB must not
      have been overloaded using the sqlite3_create_function() API.
  For the GLOB operator, the column must be indexed using the 
      built-in BINARY collating sequence.
  For the LIKE operator, if case_sensitive_like mode is enabled then
      the column must indexed using BINARY collating sequence, or if
      case_sensitive_like mode is disabled then the column must indexed
      using built-in NOCASE collating sequence.
  If the ESCAPE option is used, the ESCAPE character must be ASCII,
      or a single-byte character in UTF-8.
  


  The LIKE operator has two modes that can be set by a
  pragma.  The
  default mode is for LIKE comparisons to be insensitive to differences
  of case for latin1 characters.  Thus, by default, the following
  expression is true:

'a' LIKE 'A'


  If the case_sensitive_like pragma is enabled as follows:

PRAGMA case_sensitive_like=ON;


  Then the LIKE operator pays attention to case and the example above would
  evaluate to false.  Note that case insensitivity only applies to
  latin1 characters - basically the upper and lower case letters of English
  in the lower 127 byte codes of ASCII.  International character sets
  are case sensitive in SQLite unless an application-defined
  collating sequence and like() SQL function are provided that
  take non-ASCII characters into account.
  If an application-defined collating sequence and/or like() SQL
  function are provided, the LIKE optimization described here will never
  be taken.


  The LIKE operator is case insensitive by default because this is what
  the SQL standard requires.  You can change the default behavior at
  compile time by using the SQLITE_CASE_SENSITIVE_LIKE command-line option
  to the compiler.


  The LIKE optimization might occur if the column named on the left of the
  operator is indexed using the built-in BINARY collating sequence and
  case_sensitive_like is turned on.  Or the optimization might occur if
  the column is indexed using the built-in NOCASE collating sequence and the 
  case_sensitive_like mode is off.  These are the only two combinations
  under which LIKE operators will be optimized.


  The GLOB operator is always case sensitive.  The column on the left side
  of the GLOB operator must always use the built-in BINARY collating sequence
  or no attempt will be made to optimize that operator with indexes.


  The LIKE optimization will only be attempted if
  the right-hand side of the GLOB or LIKE operator is either
  literal string or a parameter that has been bound
  to a string literal.  The string literal must not
  begin with a wildcard; if the right-hand side begins with a wildcard
  character then this optimization is not attempted.  If the right-hand side 
  is a parameter that is bound to a string, then this optimization is
  only attempted if the prepared statement containing the expression
  was compiled with sqlite3_prepare_v2() or sqlite3_prepare16_v2().
  The LIKE optimization is not attempted if the
  right-hand side is a parameter and the statement was prepared using
  sqlite3_prepare() or sqlite3_prepare16().


  Suppose the initial sequence of non-wildcard characters on the right-hand
  side of the LIKE or GLOB operator is x.  We are using a single 
  character to denote this non-wildcard prefix but the reader should
  understand that the prefix can consist of more than 1 character.
  Let y be the smallest string that is the same length as /x/ but which
  compares greater than x.  For example, if x is
  'hello' then
  y would be 'hellp'.
  The LIKE and GLOB optimizations consist of adding two virtual terms
  like this:


  column &gt;= x AND column &lt; y


  Under most circumstances, the original LIKE or GLOB operator is still
  tested against each input row even if the virtual terms are used to
  constrain an index.  This is because we do not know what additional
  constraints may be imposed by characters to the right
  of the x prefix.  However, if there is only a single
  global wildcard to the right of x, then the original LIKE or 
  GLOB test is disabled.
  In other words, if the pattern is like this:


  column LIKE x%
  column GLOB x*


  then the original LIKE or GLOB tests are disabled when the virtual
  terms constrain an index because in that case we know that all of the
  rows selected by the index will pass the LIKE or GLOB test.


  Note that when the right-hand side of a LIKE or GLOB operator is
  a parameter and the statement is prepared using sqlite3_prepare_v2()
  or sqlite3_prepare16_v2() then the statement is automatically reparsed
  and recompiled on the first sqlite3_step() call of each run if the binding
  to the right-hand side parameter has changed since the previous run.
  This reparse and recompile is essentially the same action that occurs
  following a schema change.  The recompile is necessary so that the query
  planner can examine the new value bound to the right-hand side of the
  LIKE or GLOB operator and determine whether or not to employ the
  optimization described above.


c2: The SQLite Query Optimizer Overview
c3: 6. The Skip-Scan Optimization
c5: optoverview.html#the_skip_scan_optimization
c4:
The general rule is that indexes are only useful if there are 
  WHERE-clause constraints on the left-most columns of the index.
  However, in some cases,
  SQLite is able to use an index even if the first few columns of
  the index are omitted from the WHERE clause but later columns 
  are included.



  Consider a table such as the following:

CREATE TABLE people(
  name TEXT PRIMARY KEY,
  role TEXT NOT NULL,
  height INT NOT NULL, -- in cm
  CHECK( role IN ('student','teacher') )
);
CREATE INDEX people_idx1 ON people(role, height);



  The people table has one entry for each person in a large
  organization.  Each person is either a "student" or a "teacher",
  as determined by the "role" field.  The table also records the height in
  centimeters of each person.  The role and height are indexed.
  Notice that the left-most column of the index is not very
  selective - it only contains two possible values.



  Now consider a query to find the names of everyone in the
  organization that is 180cm tall or taller:


SELECT name FROM people WHERE height>=180;



  Because the left-most column of the index does not appear in the
  WHERE clause of the query, one is tempted to conclude that the
  index is not usable here.  However, SQLite is able to use the index.
  Conceptually, SQLite uses the index as if the query were more
  like the following:


SELECT name FROM people
 WHERE role IN (SELECT DISTINCT role FROM people)
   AND height>=180;



  Or this:

SELECT name FROM people WHERE role='teacher' AND height>=180
UNION ALL
SELECT name FROM people WHERE role='student' AND height>=180;



  The alternative query formulations shown above are conceptual only.
  SQLite does not really transform the query. 
  The actual query plan is like this:
  SQLite locates the first possible value for "role", which it
  can do by rewinding the "people_idx1" index to the beginning and reading
  the first record.  SQLite stores this first "role" value in an
  internal variable that we will here call "$role".  Then SQLite
  runs a query like: "SELECT name FROM people WHERE role=$role AND height>=180".
  This query has an equality constraint on the left-most column of the
  index and so the index can be used to resolve that query.  Once
  that query is finished, SQLite then uses the "people_idx1" index to
  locate the next value of the "role" column, using code that is logically
  similar to "SELECT role FROM people WHERE role>$role LIMIT 1".
  This new "role" value overwrites the $role variable, and the process
  repeats until all possible values for "role" have been examined.


  We call this kind of index usage a "skip-scan" because the database
  engine is basically doing a full scan of the index but it optimizes the
  scan (making it less than "full") by occasionally skipping ahead to the
  next candidate value.


  SQLite might use a skip-scan on an index if it knows that the first
  one or more columns contain many duplication values.
  If there are too few duplicates
  in the left-most columns of the index, then it would
  be faster to simply step ahead to the next value, and thus do
  a full table scan, than to do a binary search on an index to locate
  the next left-column value.


  The only way that SQLite can know that there are many duplicates
  in the left-most columns of an index
  is if the ANALYZE command has been run
  on the database.
  Without the results of ANALYZE, SQLite has to guess at the "shape" of
  the data in the table, and the default guess is that there are an average
  of 10 duplicates for every value in the left-most column of the index.
  Skip-scan only becomes profitable (it only gets to be faster than
  a full table scan) when the number of duplicates is about 18 or more.
  Hence, a skip-scan is never used on a database that has not been analyzed.


c2: The SQLite Query Optimizer Overview
c3: 7. Joins
c5: optoverview.html#joins
c4:
The ON and USING clauses of an inner join are converted into additional
  terms of the WHERE clause prior to WHERE clause analysis described
  above in paragraph 2.0.
  Thus with SQLite, there is no computational
  advantage to use the newer SQL92 join syntax
  over the older SQL89 comma-join syntax.  They both end up accomplishing
  exactly the same thing on inner joins.


  For an OUTER JOIN the situation is more complex.  The following
  two queries are not equivalent:

SELECT * FROM tab1 LEFT JOIN tab2 ON tab1.x=tab2.y;
SELECT * FROM tab1 LEFT JOIN tab2 WHERE tab1.x=tab2.y;


  For an inner join, the two queries above would be identical.  However,
  special processing applies to the ON and USING clauses of an OUTER join:
  specifically, the constraints in an ON or USING clause do not apply if
  the right table of the join is on a null row, but the constraints do apply
  in the WHERE clause.  The net effect is that putting the ON or USING
  clause expressions for a LEFT JOIN in the WHERE clause effectively converts
  the query to an
  ordinary INNER JOIN - albeit an inner join that runs more slowly.


c2: The SQLite Query Optimizer Overview
c3: 7.1. Order of Tables in a Join
c5: optoverview.html#order_of_tables_in_a_join
c4:
The current implementation of 
  SQLite uses only loop joins.  That is to say, joins are implemented as
  nested loops.


  The default order of the nested loops in a join is for the left-most
  table in the FROM clause to form the outer loop and the right-most
  table to form the inner loop.
  However, SQLite will nest the loops in a different order if doing so
  will help it to select better indexes.


  Inner joins can be freely reordered.  However a left outer join is
  neither commutative nor associative and hence will not be reordered.
  Inner joins to the left and right of the outer join might be reordered
  if the optimizer thinks that is advantageous but the outer joins are
  always evaluated in the order in which they occur.


  SQLite treats the CROSS JOIN operator specially.
  The CROSS JOIN operator is commutative, in theory.  However, SQLite chooses to
  never reorder tables in a CROSS JOIN.  This provides a mechanism
  by which the programmer can force SQLite to choose a particular loop nesting
  order.  


  When selecting the order of tables in a join, SQLite uses an efficient
  polynomial-time algorithm.  Because of this,
  SQLite is able to plan queries with 50- or 60-way joins in a matter of
  microseconds


  Join reordering is automatic and usually works well enough that
  programmers do not have to think about it, especially if ANALYZE
  has been used to gather statistics about the available indexes,
  though occasionally some hints from the programmer are needed.
  Consider, for example, the following schema:

CREATE TABLE node(
   id INTEGER PRIMARY KEY,
   name TEXT
);
CREATE INDEX node_idx ON node(name);
CREATE TABLE edge(
   orig INTEGER REFERENCES node,
   dest INTEGER REFERENCES node,
   PRIMARY KEY(orig, dest)
);
CREATE INDEX edge_idx ON edge(dest,orig);


  The schema above defines a directed graph with the ability to store a
  name at each node. Now consider a query against this schema:

SELECT *
  FROM edge AS e,
       node AS n1,
       node AS n2
 WHERE n1.name = 'alice'
   AND n2.name = 'bob'
   AND e.orig = n1.id
   AND e.dest = n2.id;


  This query asks for is all information about edges that go from
  nodes labeled "alice" to nodes labeled "bob".
  The query optimizer in SQLite has basically two choices on how to
  implement this query.  (There are actually six different choices, but
  we will only consider two of them here.)
  Pseudocode below demonstrating these two choices.



Option 1:
foreach n1 where n1.name='alice' do:
  foreach n2 where n2.name='bob' do:
    foreach e where e.orig=n1.id and e.dest=n2.id
      return n1.*, n2.*, e.*
    end
  end
end



Option 2:
foreach n1 where n1.name='alice' do:
  foreach e where e.orig=n1.id do:
    foreach n2 where n2.id=e.dest and n2.name='bob' do:
      return n1.*, n2.*, e.*
    end
  end
end


  The same indexes are used to speed up every loop in both implementation
  options.
  The only difference in these two query plans is the order in which
  the loops are nested.


  So which query plan is better? It turns out that the answer depends on
  what kind of data is found in the node and edge tables.


  Let the number of alice nodes be M and the number of bob nodes be N.
  Consider two scenarios. In the first scenario, M and N are both 2 but
  there are thousands of edges on each node. In this case, option 1 is
  preferred. With option 1, the inner loop checks for the existence of
  an edge between a pair of nodes and outputs the result if found. 
  Because there are only 2 alice and bob nodes each, the inner loop
  only has to run four times and the query is very quick. Option 2 would
  take much longer here. The outer loop of option 2 only executes twice,
  but because there are a large number of edges leaving each alice node,
  the middle loop has to iterate many thousands of times. It will be
  much slower. So in the first scenario, we prefer to use option 1.


  Now consider the case where M and N are both 3500. Alice nodes are
  abundant.  This time suppose each of these nodes is connected by only one
  or two edges. Now option 2 is preferred. With option 2,
  the outer loop still has to run 3500 times, but the middle loop only
  runs once or twice for each outer loop and the inner loop will only
  run once for each middle loop, if at all. So the total number of
  iterations of the inner loop is around 7000. Option 1, on the other
  hand, has to run both its outer loop and its middle loop 3500 times
  each, resulting in 12 million iterations of the middle loop.
  Thus in the second scenario, option 2 is nearly 2000 times faster
  than option 1.


  So you can see that depending on how the data is structured in the table,
  either query plan 1 or query plan 2 might be better.  Which plan does
  SQLite choose by default?  As of version 3.6.18, without running ANALYZE,
  SQLite will choose option 2.
  If the ANALYZE command is run in order to gather statistics,
  a different choice might be made if the statistics indicate that the
  alternative is likely to run faster.


c2: The SQLite Query Optimizer Overview
c3: 7.2. Manual Control Of Query Plans Using SQLITE_STAT Tables
c5: optoverview.html#manual_control_of_query_plans_using_sqlite_stat_tables
c4:
SQLite provides the ability for advanced programmers to exercise control
  over the query plan chosen by the optimizer. One method for doing this
  is to fudge the ANALYZE results in the sqlite_stat1, 
  sqlite_stat3, and/or sqlite_stat4 tables.  This is not
  recommended for most situations.


c2: The SQLite Query Optimizer Overview
c3: 7.3. Manual Control of Query Plans using CROSS JOIN
c5: optoverview.html#manual_control_of_query_plans_using_cross_join
c4:
Programmers can force SQLite to use a particular loop nesting order
  for a join by using the CROSS JOIN operator instead of just JOIN, 
  INNER JOIN, NATURAL JOIN, or a "," join.  Though CROSS JOINs are
  commutative in theory, SQLite chooses to never reorder the tables in
  a CROSS JOIN.  Hence, the left table of a CROSS JOIN will always be
  in an outer loop relative to the right table.


  In the following query, the optimizer is free to reorder the 
  tables of FROM clause any way it sees fit:

SELECT *
  FROM node AS n1,
       edge AS e,
       node AS n2
 WHERE n1.name = 'alice'
   AND n2.name = 'bob'
   AND e.orig = n1.id
   AND e.dest = n2.id;


  In the following logically equivalent formulation of the same query,
  the substitution of "CROSS JOIN" for the "," means that the order
  of tables must be N1, E, N2.

SELECT *
  FROM node AS n1 CROSS JOIN
       edge AS e CROSS JOIN
       node AS n2
 WHERE n1.name = 'alice'
   AND n2.name = 'bob'
   AND e.orig = n1.id
   AND e.dest = n2.id;


  In the latter query, the query plan must be 
  option 2.  Note that
  you must use the keyword "CROSS" in order to disable the table reordering
  optimization; INNER JOIN, NATURAL JOIN, JOIN, and other similar
  combinations work just like a comma join in that the optimizer is
  free to reorder tables as it sees fit. (Table reordering is also
  disabled on an outer join, but that is because outer joins are not
  associative or commutative. Reordering tables in OUTER JOIN changes
  the result.)


  See "The Fossil NGQP Upgrade Case Study" for another real-world example
  of using CROSS JOIN to manually control the nesting order of a join.
  The query planner checklist found later in the same document provides
  further guidance on manual control of the query planner.


c2: The SQLite Query Optimizer Overview
c3: 8. Choosing Between Multiple Indexes
c5: optoverview.html#choosing_between_multiple_indexes
c4:
Each table in the FROM clause of a query can use at most one index
  (except when the OR-clause optimization comes into
  play)
  and SQLite strives to use at least one index on each table.  Sometimes,
  two or more indexes might be candidates for use on a single table.
  For example:

CREATE TABLE ex2(x,y,z);
CREATE INDEX ex2i1 ON ex2(x);
CREATE INDEX ex2i2 ON ex2(y);
SELECT z FROM ex2 WHERE x=5 AND y=6;


  For the SELECT statement above, the optimizer can use the ex2i1 index
  to lookup rows of ex2 that contain x=5 and then test each row against
  the y=6 term.  Or it can use the ex2i2 index to lookup rows
  of ex2 that contain y=6 then test each of those rows against the
  x=5 term.


  When faced with a choice of two or more indexes, SQLite tries to estimate
  the total amount of work needed to perform the query using each option.
  It then selects the option that gives the least estimated work.


  To help the optimizer get a more accurate estimate of the work involved
  in using various indexes, the user may optionally run the ANALYZE command.
  The ANALYZE command scans all indexes of database where there might
  be a choice between two or more indexes and gathers statistics on the
  selectiveness of those indexes.  The statistics gathered by
  this scan are stored in special database tables names shows names all
  begin with "sqlite_stat".
  The content of these tables is not updated as the database
  changes so after making significant changes it might be prudent to
  rerun ANALYZE.
  The results of an ANALYZE command are only available to database connections
  that are opened after the ANALYZE command completes.


  The various sqlite_statN tables contain information on how
  selective the various indexes are.  For example, the sqlite_stat1
  table might indicate that an equality constraint on column x reduces the
  search space to 10 rows on average, whereas an equality constraint on
  column y reduces the search space to 3 rows on average.  In that case,
  SQLite would prefer to use index ex2i2 since that index is more selective.


c2: The SQLite Query Optimizer Overview
c3: 8.1. Disqualifying WHERE Clause Terms using Unary-"+"
c5: optoverview.html#disqualifying_where_clause_terms_using_unary_
c4:
Terms of the WHERE clause can be manually disqualified for use with
  indexes by prepending a unary + operator to the column name.  The
  unary + is a no-op and will not generate any byte code in the prepared
  statement.
  However, the unary + operator will prevent the term from
  constraining an index.
  So, in the example above, if the query were rewritten as:

SELECT z FROM ex2 WHERE +x=5 AND y=6;


  The + operator on the x column will prevent that term from 
  constraining an index.  This would force the use of the ex2i2 index.


  Note that the unary + operator also removes 
  type affinity from
  an expression, and in some cases this can cause subtle changes in
  the meaning of an expression.
  In the example above,
  if column x has TEXT affinity
  then the comparison "x=5" will be done as text.  The + operator
  removes the affinity.  So the comparison "+x=5" will compare the text
  in column x with the numeric value 5 and will always be false.


c2: The SQLite Query Optimizer Overview
c3: 8.2. Range Queries
c5: optoverview.html#range_queries
c4:
Consider a slightly different scenario:

CREATE TABLE ex2(x,y,z);
CREATE INDEX ex2i1 ON ex2(x);
CREATE INDEX ex2i2 ON ex2(y);
SELECT z FROM ex2 WHERE x BETWEEN 1 AND 100 AND y BETWEEN 1 AND 100;


  Further suppose that column x contains values spread out
  between 0 and 1,000,000 and column y contains values
  that span between 0 and 1,000.  In that scenario,
  the range constraint on column x should reduce the search space by
  a factor of 10,000 whereas the range constraint on column y should
  reduce the search space by a factor of only 10.  So the ex2i1 index
  should be preferred.


  SQLite will make this determination, but only if it has been compiled
  with SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4.
  The SQLITE_ENABLE_STAT3 and SQLITE_ENABLE_STAT4 options causes
  the ANALYZE command to collect a histogram of column content in the
  sqlite_stat3 or sqlite_stat4 tables and to use this histogram to 
  make a better guess at the best query to use for range constraints
  such as the above.  The main difference between STAT3 and STAT4 is
  that STAT3 records histogram data for only the left-most column of
  an index whereas STAT4 records histogram data for all columns of an
  index.  For single-column indexes, STAT3 and STAT4 work the same.


  The histogram data is only useful if the right-hand side of the constraint
  is a simple compile-time constant or parameter and not an expression.


  Another limitation of the histogram data is that it only applies to the
  left-most column on an index.  Consider this scenario:

CREATE TABLE ex3(w,x,y,z);
CREATE INDEX ex3i1 ON ex2(w, x);
CREATE INDEX ex3i2 ON ex2(w, y);
SELECT z FROM ex3 WHERE w=5 AND x BETWEEN 1 AND 100 AND y BETWEEN 1 AND 100;


  Here the inequalities are on columns x and y which are not the
  left-most index columns.  Hence, the histogram data which is collected no
  left-most column of indexes is useless in helping to choose between the
  range constraints on columns x and y.


c2: The SQLite Query Optimizer Overview
c3: 9. Covering Indexes
c5: optoverview.html#covering_indexes
c4:
When doing an indexed lookup of a row, the usual procedure is to
  do a binary search on the index to find the index entry, then extract
  the rowid from the index and use that rowid to do a binary search on
  the original table.  Thus a typical indexed lookup involves two
  binary searches.
  If, however, all columns that were to be fetched from the table are
  already available in the index itself, SQLite will use the values
  contained in the index and will never look up the original table
  row.  This saves one binary search for each row and can make many
  queries run twice as fast.


  When an index contains all of the data needed for a query and when the
  original table never needs to be consulted, we call that index a
  "covering index".


c2: The SQLite Query Optimizer Overview
c3: 10. ORDER BY Optimizations
c5: optoverview.html#order_by_optimizations
c4:
SQLite attempts to use an index to satisfy the ORDER BY clause of a
  query when possible.
  When faced with the choice of using an index to satisfy WHERE clause
  constraints or satisfying an ORDER BY clause, SQLite does the same
  cost analysis described above
  and chooses the index that it believes will result in the fastest answer.


  SQLite will also attempt to use indexes to help satisfy GROUP BY clauses
  and the DISTINCT keyword.  If the nested loops of the join can be arranged
  such that rows that are equivalent for the GROUP BY or for the DISTINCT are
  consecutive, then the GROUP BY or DISTINCT logic can determine if the 
  current row is part of the same group or if the current row is distinct
  simply by comparing the current row to the previous row.
  This can be much faster than the alternative of comparing each row to
  all prior rows.


c2: The SQLite Query Optimizer Overview
c3: 10.1. Partial ORDER BY via Index
c5: optoverview.html#partial_order_by_via_index
c4:
If a query contains an ORDER BY clause with multiple terms, it might
  be that SQLite can use indexes to cause rows to come out in the order
  of some prefix of the terms in the ORDER BY but that later terms in
  the ORDER BY are not satisfied.  In that case, SQLite does block sorting.
  Suppose the ORDER BY clause has four terms and the natural order of the
  query results in rows appearing in order of the first two terms.  As
  each row is output by the query engine and enters the sorter, the 
  outputs in the current row corresponding to the first two terms of 
  the ORDER BY are compared against the previous row.  If they have
  changed, the current sort is finished and output and a new sort is
  started.  This results in a slightly faster sort.  Event bigger
  advantages are that many fewer rows need to be held in memory,
  reducing memory requirements, and outputs can begin to appear before
  the core query has run to completion.


c2: The SQLite Query Optimizer Overview
c3: 11. Subquery Flattening
c5: optoverview.html#subquery_flattening
c4:
When a subquery occurs in the FROM clause of a SELECT, the simplest
  behavior is to evaluate the subquery into a transient table, then run
  the outer SELECT against the transient table.  Such a plan
  can be suboptimal since the transient table will not have any indexes
  and the outer query (which is likely a join) will be forced to do a
  full table scan on the transient table.


  To overcome this problem, SQLite attempts to flatten subqueries in
  the FROM clause of a SELECT.
  This involves inserting the FROM clause of the subquery into the
  FROM clause of the outer query and rewriting expressions in
  the outer query that refer to the result set of the subquery.
  For example:

SELECT t1.a, t2.b FROM t2, (SELECT x+y AS a FROM t1 WHERE z&lt;100) WHERE a&gt;5


  Would be rewritten using query flattening as:

SELECT t1.x+t1.y AS a, t2.b FROM t2, t1 WHERE z&lt;100 AND a&gt;5


  There is a long list of conditions that must all be met in order for
  query flattening to occur.  Some of the constraints are marked as 
  obsolete by italic text.  These extra constraints are retained in the
  documentation to preserve the numbering of the other constraints.


  Casual readers are not expected to understand all of these rules.
  A key take-away from this section is that the rules for determining
  if query flatting is safe or unsafe are subtle and
  complex.  There have been multiple bugs over the years caused by
  over-aggressive query flattening.  On the other hand, performance
  of complex queries and/or queries involving views tends to suffer
  if query flattening is more conservative.


  
    (Obsolete.  Query flattening is no longer
                      attempted for aggregate subqueries.)

    (Obsolete.  Query flattening is no longer
                      attempted for aggregate subqueries.)

  
  If the subquery is the right operand of a LEFT JOIN then
    the subquery may not be a join, and
    the FROM clause of the subquery may
   not contain a virtual table, and
    the outer query may not be an aggregate.

    The subquery is not DISTINCT.

   (Subsumed into constraint 4)

   (Obsolete.  Query flattening is no longer
                      attempted for aggregate subqueries.)

  
  The subquery has a FROM clause.

  
  The subquery does not use LIMIT or the outer query is not a join.

  
  The subquery does not use LIMIT or the outer query does not use
  aggregates.

   (Restriction relaxed in 2005)

  
  The subquery and the outer query do not both have ORDER BY clauses.

   (Subsumed into constraint 3)

    The subquery and outer query do not both use LIMIT.

    The subquery does not use OFFSET.

  
  If the outer query is part of a compound select, then the
  subquery may not have a LIMIT clause.

  
  If the outer query is an aggregate, then the subquery may
  not contain ORDER BY. 

  
  If the sub-query is a compound SELECT, then
  
   all compound operators must be UNION ALL, and
   no terms with the subquery compound may be aggregate
       or DISTINCT, and
   every term within the subquery must have a FROM clause, and
   the outer query may not be an aggregate, DISTINCT query, or join.
  

  The parent and sub-query may contain WHERE clauses. Subject to
  rules (11), (12) and (13), they may also contain ORDER BY,
  LIMIT and OFFSET clauses.

  
  If the sub-query is a compound select, then all terms of the
  ORDER by clause of the parent must be simple references to 
  columns of the sub-query.

  
  If the subquery uses LIMIT then the outer query may not
  have a WHERE clause.

  
  If the sub-query is a compound select, then it must not use
   an ORDER BY clause.

  
  If the subquery uses LIMIT, then the outer query may not be
  DISTINCT.

   The subquery may not be a recursive CTE.

   (Subsumed into constraint 17d.)

   (Obsolete. Query flattening is no longer
                      attempted for aggregate subqueries.)
  



  Query flattening is an important optimization when views are used as
  each use of a view is translated into a subquery.


c2: The SQLite Query Optimizer Overview
c3: 12. Subquery Co-routines
c5: optoverview.html#subquery_co_routines
c4:
Prior to SQLite 3.7.15 (2012-12-12),
  a subquery in the FROM clause would be
  either flattened into the outer query, or else the subquery would be run
  to completion
  before the outer query started, the result set from the subquery
  would be stored in a transient table,
  and then the transient table would be used in the outer query.  Newer
  versions of SQLite have a third option, which is to implement the subquery
  using a co-routine.


  A co-routine is like a subroutine in that it runs in the same thread
  as the caller and eventually returns control back to the caller.  The
  difference is that a co-routine also has the ability to return
  before it has finished, and then resume where it left off the next
  time it is called.


  When a subquery is implemented as a co-routine, byte-code is generated
  to implement the subquery as if it were a standalone query, except
  instead of returning rows of results back to the application, the
  co-routine yields control back to the caller after each row is computed.
  The caller can then use that one computed row as part of its computation,
  then invoke the co-routine again when it is ready for the next row.


  Co-routines are better than storing the complete result set of the subquery
  in a transient table because co-routines use less memory.  With a co-routine,
  only a single row of the result needs to be remembered, whereas all rows of
  the result must be stored for a transient table.  Also, because the
  co-routine does not need to run to completion before the outer query
  begins its work, the first rows of output can appear much sooner, and if
  the overall query is aborted, less work is done overall.


  On the other hand, if the result of the subquery must be scanned multiple
  times (because, for example, it is just one table in a join) then it
  is better to use a transient table to remember the entire result of the
  subquery, in order to avoid computing the subquery more than once.


c2: The SQLite Query Optimizer Overview
c3: 12.1. Using Co-routines to Defer Work until after the Sorting
c5: optoverview.html#using_co_routines_to_defer_work_until_after_the_sorting
c4:
As of SQLite version 3.21.0 (2017-10-24), the query planner will
  always prefer to use a co-routine to implement FROM-clause subqueries 
  that contains an ORDER BY clause and that are not part of a join when
  the result set of the outer query is "complex".  This feature allows
  applications to shift expensive computations from before the
  sorter until after the sorter, which can result in faster operation.
  For example, consider this query:

SELECT expensive_function(a) FROM tab ORDER BY date DESC LIMIT 5;


  The goal of this query is to compute some value for the five most
  recent entries in the table.  In the query above, the
  "expensive_function()" is invoked prior to the sort and thus is
  invoked on every row of the table, even
  rows that are ultimately omitted due to the LIMIT clause.
  A co-routine can be used to work around this:

SELECT expensive_function(a) FROM (
  SELECT a FROM tab ORDER BY date DESC LIMIT 5
);


  In the revised query, the subquery implemented by a co-routine computes
  the five most recent values for "a".  Those five values are passed from the
  co-routine up into the outer query where the "expensive_function()" is
  invoked on only the specific rows that the application cares about.


  The query planner in future versions of SQLite might grow smart enough
  to make transformations such as the above automatically, in both directions.
  That is to say, future versions of SQLite might transform queries of the
  first form into the second, or queries written the second way into the
  first.  As of SQLite version 3.22.0 (2018-01-22), the query planner
  will flatten the subquery if the outer query does not make use of any
  user-defined functions or subqueries in its result set.  For the examples
  shown above, however, SQLite implements each of the queries as
  written.


c2: The SQLite Query Optimizer Overview
c3: 13. The MIN/MAX Optimization
c5: optoverview.html#the_min_max_optimization
c4:
Queries that contain a single MIN() or MAX() aggregate function whose
  argument is the left-most column of an index might be satisfied
  by doing a single index lookup rather than by scanning the entire table.
  Examples:

SELECT MIN(x) FROM table;
SELECT MAX(x)+1 FROM table;


c2: The SQLite Query Optimizer Overview
c3: 14. Automatic Indexes
c5: optoverview.html#automatic_indexes
c4:
When no indexes are available to aid the evaluation of a query, SQLite
  might create an automatic index that lasts only for the duration
  of a single SQL statement.
  Since the cost of constructing the automatic index is
  O(NlogN) (where N is the number of entries in the table) and the cost of
  doing a full table scan is only O(N), an automatic index will
  only be created if SQLite expects that the lookup will be run more than
  logN times during the course of the SQL statement. Consider an example:

CREATE TABLE t1(a,b);
CREATE TABLE t2(c,d);
-- Insert many rows into both t1 and t2
SELECT * FROM t1, t2 WHERE a=c;


  In the query above, if both t1 and t2 have approximately N rows, then
  without any indexes the query will require O(N*N) time.  On the other
  hand, creating an index on table t2 requires O(NlogN) time and using
  that index to evaluate the query requires an additional O(NlogN) time.
  In the absence of ANALYZE information, SQLite guesses that N is one
  million and hence it believes that constructing the automatic index will
  be the cheaper approach.


  An automatic index might also be used for a subquery:

CREATE TABLE t1(a,b);
CREATE TABLE t2(c,d);
-- Insert many rows into both t1 and t2
SELECT a, (SELECT d FROM t2 WHERE c=b) FROM t1;


  In this example, the t2 table is used in a subquery to translate values
  of the t1.b column.  If each table contains N rows, SQLite expects that
  the subquery will run N times, and hence it will believe it is faster
  to construct an automatic, transient index on t2 first and then use
  that index to satisfy the N instances of the subquery.


  The automatic indexing capability can be disabled at run-time using
  the automatic_index pragma.  Automatic indexing is turned on by
  default, but this can be changed so that automatic indexing is off
  by default using the SQLITE_DEFAULT_AUTOMATIC_INDEX compile-time option.
  The ability to create automatic indexes can be completely disabled by
  compiling with the SQLITE_OMIT_AUTOMATIC_INDEX compile-time option.


  In SQLite version 3.8.0 (2013-08-26) and later, 
  an SQLITE_WARNING_AUTOINDEX message is sent
  to the error log every time a statement is prepared that uses an
  automatic index.  Application developers can and should use these warnings
  to identify the need for new persistent indexes in the schema.


  Do not confuse automatic indexes with the internal indexes (having names
  like "sqlite_autoindex_table_N") that are sometimes
  created to implement a PRIMARY KEY constraint or UNIQUE constraint.
  The automatic indexes described here exist only for the duration of a
  single query, are never persisted to disk, and are only visible to a
  single database connection.  Internal indexes are part of the implementation
  of PRIMARY KEY and UNIQUE constraints, are long-lasting and persisted
  to disk, and are visible to all database connections.  The term "autoindex"
  appears in the names of internal indexes for legacy reasons and does
  not indicate that internal indexes and automatic indexes are related.


c2: The SQLite Query Optimizer Overview
c3: 14.1. Hash Joins
c5: optoverview.html#hash_joins
c4:
An automatic index is about the same thing as a
 hash join.  The only difference
 is that a B-Tree is used instead of a hash table.  If you are willing to
 say that the transient B-Tree constructed for an automatic index is
 really just a fancy hash table, then a query that uses an automatic
 index is just a hash join.


 SQLite constructs an transient index instead of a hash table in this
 instance because it already has a robust and high performance B-Tree
 implementation at hand, whereas a hash-table would need to be added.
 Adding a separate hash table implementation to handle this one case
 would increase the size of the library (which is designed for use on
 low-memory embedded devices) for minimal performance gain.  SQLite might
 be enhanced with a hash-table implementation someday, but for now it seems
 better to continue using automatic indexes in cases where client/server
 database engines might use a hash join.


c2: The SQLite Query Optimizer Overview
c3: 15. The Push-Down Optimization
c5: optoverview.html#the_push_down_optimization
c4:
If a subquery cannot be flattened into the outer query, it might
  still be possible to enhance performance by "pushing down" WHERE clause
  terms from the outer query into the subquery.  Consider an example:

CREATE TABLE t1(a INT, b INT);
CREATE TABLE t2(x INT, y INT);
CREATE VIEW v1(a,b) AS SELECT DISTINCT a, b FROM t1;

SELECT x, y, b
  FROM t2 JOIN v1 ON (x=a)
 WHERE b BETWEEN 10 AND 20;



  The view v1 cannot be flattened because it is DISTINCT.  It must
  instead be run as a subquery with the results being stored in a
  transient table, then the join is performed between t2 and the
  transient table.  The push-down optimization pushes down the
  "b BETWEEN 10 AND 20" term into the view.  This makes the transient
  table smaller, and helps the subquery to run faster if there
  is an index on t1.b.  The resulting evaluation is like this:

SELECT x, y, b
  FROM t2
  JOIN (SELECT DISTINCT a, b FROM t1 WHERE b BETWEEN 10 AND 20)
 WHERE b BETWEEN 10 AND 20;



  The push-down optimization cannot always be used.  For example,
  if the subquery contains a LIMIT, then pushing down any part of
  the WHERE clause from the outer query could change the result of
  the inner query.  There are other restrictions, explained in a
  comment in the source code on the pushDownWhereTerms() routine
  that implements this optimization.


c2: The SQLite Query Optimizer Overview
c3: 16. The LEFT JOIN Strength Reduction Optimization
c5: optoverview.html#the_left_join_strength_reduction_optimization
c4:
A LEFT JOIN can sometimes be converted into an ordinary JOIN
  if there are terms in the WHERE clause that guarantee that the
  two joins will give identical results.  In particular, if any
  column in the right-hand table of the LEFT JOIN must be non-NULL
  in order for the WHERE clause to be true, then the LEFT JOIN is
  demoted to an ordinary JOIN.


  The prover that determines whether any column of the right-hand
  table of a LEFT JOIN must be non-NULL in the WHERE clause is
  imperfect.  It sometimes returns a false negative.  In other words,
  it sometimes fails to reduce the strength of a LEFT JOIN when doing
  so was in fact possible.  For example, the prover does not know
  the datetime() SQL function will always return NULL if its first
  argument is NULL, and so it will not recognize that the LEFT JOIN
  in the following query could be strength-reduced:

SELECT urls.url
  FROM urls
  LEFT JOIN
    (SELECT *
      FROM (SELECT url_id AS uid, max(retrieval_time) AS rtime
              FROM lookups GROUP BY 1 ORDER BY 1)
      WHERE uid IN (358341,358341,358341)
    ) recent
    ON u.source_seed_id = recent.xyz OR u.url_id = recent.xyz
 WHERE
     DATETIME(recent.rtime) > DATETIME('now', '-5 days');



  It is possible that future enhancements to the prover might enable it
  to recognize that NULL inputs to certain built-in functions
  always result in a NULL answer.  However, not all built-in
  functions have that property (for example coalesce()) and, of
  course, the prover will never be able to reason about
  application-defined SQL functions.


c2: The SQLite Query Optimizer Overview
c3: 17. The Omit LEFT JOIN Optimization
c5: optoverview.html#the_omit_left_join_optimization
c4:
Sometimes a LEFT JOIN can be completely omitted from a query without
  changing the result.  This can happen if all of the following are
  true:


  
   The query is not an aggregate
   Either the query is DISTINCT or else the ON or USING clause
       on the LEFT JOIN constrains the join such that it matches
       only a single row
   The right-hand table of the LEFT JOIN is not be used anywhere
       in the query outside of its own USING or ON clause.
  


  LEFT JOIN elimination often comes up when LEFT JOINs are used
  inside of views, and then the view is used in such as way that
  none of the columns of the right-hand table of the LEFT JOIN are
  referenced.


  Here is a simple example of omitting a LEFT JOIN:

CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3);

SELECT v1, v3 FROM t1 
  LEFT JOIN t2 ON (t1.ipk=t2.ipk)
  LEFT JOIN t3 ON (t1.ipk=t3.ipk)



  The t2 table is completely unused in the query above, and so the
  query planner is able to implement the query as if it were written:

SELECT v1, v3 FROM t1 
  LEFT JOIN t3 ON (t1.ipk=t3.ipk)


c2: The SQLite Query Optimizer Overview
c3: 18. The Constant Propagation Optimization
c5: optoverview.html#the_constant_propagation_optimization
c4:
When a WHERE clause contains two or more equality constraints connected
  by the AND operator such that all of the affinities of the various
  constraints are the same, then SQLite might use the transitive property
  of equality to construct new "virtual" constraints that can be used to
  simplify expressions and/or improve performance.  This is called the
  "constant-propagation optimization".


  For example, consider the following schema and query:

CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT);
SELECT * FROM t1 WHERE a=b AND b=5;



  SQLite looks at the "a=b" and "b=5" constraints and deduces that
  if those two constraints are true, then it must also be the case
  that "a=5" is true.  This means that the desired row can be looked up
  quickly using a value of 5 for the INTEGER PRIMARY KEY.
This page last modified on  2022-09-19 12:27:16 UTC


c2: The Virtual Table Mechanism Of SQLite
c3: 1. Introduction
c5: vtab.html#introduction
c4:
A virtual table is an object that is registered with an open SQLite
database connection. From the perspective of an SQL statement,
the virtual table object looks like any other table or view. 
But behind the scenes, queries and updates on a virtual table
invoke callback methods of the virtual table object instead of
reading and writing on the database file.

The virtual table mechanism allows an application to publish
interfaces that are accessible from SQL statements as if they were
tables. SQL statements can do almost anything to a
virtual table that they can do to a real table, with the following
exceptions:



 One cannot create a trigger on a virtual table.
 One cannot create additional indices on a virtual table. 
     (Virtual tables can have indices but that must be built into
     the virtual table implementation.  Indices cannot be added
     separately using CREATE INDEX statements.)
 One cannot run ALTER TABLE ... ADD COLUMN
     commands against a virtual table.


Individual virtual table implementations might impose additional
constraints. For example, some virtual implementations might provide
read-only tables. Or some virtual table implementations might allow
INSERT or DELETE but not UPDATE.  Or some virtual table implementations
might limit the kinds of UPDATEs that can be made.

A virtual table might represent an in-memory data structures. 
Or it might represent a view of data on disk that is not in the
SQLite format. Or the application might compute the content of the 
virtual table on demand.

Here are some existing and postulated uses for virtual tables:


 A full-text search interface
 Spatial indices using R-Trees
 Introspect the disk content of an SQLite database file
     (the dbstat virtual table)
 Read and/or write the content of a comma-separated value (CSV)
     file
 Access the filesystem of the host computer as if it were a database table
 Enabling SQL manipulation of data in statistics packages like R


See the list of virtual tables page for a longer list of actual
virtual table implementations.


c2: The Virtual Table Mechanism Of SQLite
c3: 1.1. Usage
c5: vtab.html#usage
c4:
A virtual table is created using a CREATE VIRTUAL TABLE statement.

create-virtual-table-stmt:
hide
 
 




The CREATE VIRTUAL TABLE statement creates a new table
called table-name derived from the class
module-name.  The module-name
is the name that is registered for the virtual table by
the sqlite3_create_module() interface.

CREATE VIRTUAL TABLE tablename USING modulename;


One can also provide comma-separated arguments to the module following 
the module name:

CREATE VIRTUAL TABLE tablename USING modulename(arg1, arg2, ...);


The format of the arguments to the module is very general. Each 
module-argument
may contain keywords, string literals, identifiers, numbers, and 
punctuation. Each module-argument is passed as 
written (as text) into the
constructor method of the virtual table implementation 
when the virtual 
table is created and that constructor is responsible for parsing and 
interpreting the arguments. The argument syntax is sufficiently general 
that a virtual table implementation can, if it wants to, interpret its
arguments as column definitions in an ordinary CREATE TABLE statement. 
The implementation could also impose some other interpretation on the 
arguments.

Once a virtual table has been created, it can be used like any other 
table with the exceptions noted above and imposed by specific virtual
table implementations. A virtual table is destroyed using the ordinary
DROP TABLE syntax.


c2: The Virtual Table Mechanism Of SQLite
c3: 1.1.1. Temporary virtual tables
c5: vtab.html#temporary_virtual_tables
c4:
There is no "CREATE TEMP VIRTUAL TABLE" statement.  To create a
temporary virtual table, add the "temp" schema
before the virtual table name.

CREATE VIRTUAL TABLE temp.tablename USING module(arg1, ...);


c2: The Virtual Table Mechanism Of SQLite
c3: 1.1.2. Eponymous virtual tables
c5: vtab.html#eponymous_virtual_tables
c4:
Some virtual tables exist automatically in the "main" schema of
every database connection in which their
module is registered, even without a CREATE VIRTUAL TABLE statement.
Such virtual tables are called "eponymous virtual tables".
To use an eponymous virtual table, simply use the 
module name as if it were a table.
Eponymous virtual tables exist in the "main" schema only, so they will
not work if prefixed with a different schema name.

An example of an eponymous virtual table is the dbstat virtual table.
To use the dbstat virtual table as an eponymous virtual table, 
simply query against the "dbstat"
module name, as if it were an ordinary table.  (Note that SQLite
must be compiled with the SQLITE_ENABLE_DBSTAT_VTAB option to include
the dbstat virtual table in the build.)

SELECT * FROM dbstat;


A virtual table is eponymous if its xCreate method is the exact same
function as the xConnect method, or if the xCreate method is NULL.
The xCreate method is called when a virtual table is first created
using the CREATE VIRTUAL TABLE statement.  The xConnect method 
is invoked whenever
a database connection attaches to or reparses a schema. When these two methods
are the same, that indicates that the virtual table has no persistent
state that needs to be created and destroyed.


c2: The Virtual Table Mechanism Of SQLite
c3: 1.1.3. Eponymous-only virtual tables
c5: vtab.html#eponymous_only_virtual_tables
c4:
If the xCreate method is NULL, then
CREATE VIRTUAL TABLE statements are prohibited for that virtual table,
and the virtual table is an "eponymous-only virtual table".
Eponymous-only virtual tables are useful as 
table-valued functions.


Note that prior to version 3.9.0 (2015-10-14), 
SQLite did not check the xCreate method
for NULL before invoking it.  So if an eponymous-only virtual table is
registered with SQLite version 3.8.11.1 (2015-07-29)
or earlier and a CREATE VIRTUAL TABLE
command is attempted against that virtual table module, a jump to a NULL
pointer will occur, resulting in a crash.


c2: The Virtual Table Mechanism Of SQLite
c3: 1.2. Implementation
c5: vtab.html#implementation
c4:
Several new C-level objects are used by the virtual table implementation:

typedef struct sqlite3_vtab sqlite3_vtab;
typedef struct sqlite3_index_info sqlite3_index_info;
typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
typedef struct sqlite3_module sqlite3_module;


The sqlite3_module structure defines a module object used to implement
a virtual table. Think of a module as a class from which one can 
construct multiple virtual tables having similar properties. For example,
one might have a module that provides read-only access to 
comma-separated-value (CSV) files on disk. That one module can then be
used to create several virtual tables where each virtual table refers
to a different CSV file.

The module structure contains methods that are invoked by SQLite to
perform various actions on the virtual table such as creating new
instances of a virtual table or destroying old ones, reading and
writing data, searching for and deleting, updating, or inserting rows. 
The module structure is explained in more detail below.

Each virtual table instance is represented by an sqlite3_vtab structure. 
The sqlite3_vtab structure looks like this:

struct sqlite3_vtab {
  const sqlite3_module *pModule;
  int nRef;
  char *zErrMsg;
};


Virtual table implementations will normally subclass this structure 
to add additional private and implementation-specific fields. 
The nRef field is used internally by the SQLite core and should not 
be altered by the virtual table implementation. The virtual table 
implementation may pass error message text to the core by putting 
an error message string in zErrMsg.
Space to hold this error message string must be obtained from an
SQLite memory allocation function such as sqlite3_mprintf() or
sqlite3_malloc().
Prior to assigning a new value to zErrMsg, the virtual table 
implementation must free any preexisting content of zErrMsg using 
sqlite3_free(). Failure to do this will result in a memory leak. 
The SQLite core will free and zero the content of zErrMsg when it 
delivers the error message text to the client application or when 
it destroys the virtual table. The virtual table implementation only 
needs to worry about freeing the zErrMsg content when it overwrites 
the content with a new, different error message.

The sqlite3_vtab_cursor structure represents a pointer to a specific
row of a virtual table. This is what an sqlite3_vtab_cursor looks like:

struct sqlite3_vtab_cursor {
  sqlite3_vtab *pVtab;
};


Once again, practical implementations will likely subclass this 
structure to add additional private fields.

The sqlite3_index_info structure is used to pass information into
and out of the xBestIndex method of the module that implements a 
virtual table.

Before a CREATE VIRTUAL TABLE statement can be run, the module 
specified in that statement must be registered with the database 
connection. This is accomplished using either of the sqlite3_create_module()
or sqlite3_create_module_v2() interfaces:

int sqlite3_create_module(
  sqlite3 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite3_module *,    /* Methods for the module */
  void *                     /* Client data for xCreate/xConnect */
);
int sqlite3_create_module_v2(
  sqlite3 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite3_module *,    /* Methods for the module */
  void *,                    /* Client data for xCreate/xConnect */
  void(*xDestroy)(void*)     /* Client data destructor function */
);


The sqlite3_create_module() and sqlite3_create_module_v2()
routines associates a module name with 
an sqlite3_module structure and a separate client data that is specific 
to each module.  The only difference between the two create_module methods
is that the _v2 method includes an extra parameter that specifies a
destructor for client data pointer.  The module structure is what defines
the behavior of a virtual table.  The module structure looks like this:


struct sqlite3_module {
  int iVersion;
  int (*xCreate)(sqlite3*, void *pAux,
               int argc, char *const*argv,
               sqlite3_vtab **ppVTab,
               char **pzErr);
  int (*xConnect)(sqlite3*, void *pAux,
               int argc, char *const*argv,
               sqlite3_vtab **ppVTab,
               char **pzErr);
  int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
  int (*xDisconnect)(sqlite3_vtab *pVTab);
  int (*xDestroy)(sqlite3_vtab *pVTab);
  int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
  int (*xClose)(sqlite3_vtab_cursor*);
  int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
                int argc, sqlite3_value **argv);
  int (*xNext)(sqlite3_vtab_cursor*);
  int (*xEof)(sqlite3_vtab_cursor*);
  int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
  int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid);
  int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite_int64 *);
  int (*xBegin)(sqlite3_vtab *pVTab);
  int (*xSync)(sqlite3_vtab *pVTab);
  int (*xCommit)(sqlite3_vtab *pVTab);
  int (*xRollback)(sqlite3_vtab *pVTab);
  int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
                     void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
                     void **ppArg);
  int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
  /* The methods above are in version 1 of the sqlite_module object. Those 
  ** below are for version 2 and greater. */
  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
  int (*xRelease)(sqlite3_vtab *pVTab, int);
  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
  /* The methods above are in versions 1 and 2 of the sqlite_module object.
  ** Those below are for version 3 and greater. */
  int (*xShadowName)(const char*);
};


The module structure defines all of the methods for each virtual 
table object. The module structure also contains the iVersion field which
defines the particular edition of the module table structure. Currently, 
iVersion is always 3 or less, but in future releases of SQLite the module
structure definition might be extended with additional methods and in 
that case the maximum iVersion value will be increased.

The rest of the module structure consists of methods used to implement
various features of the virtual table. Details on what each of these 
methods do are provided in the sequel.


c2: The Virtual Table Mechanism Of SQLite
c3: 1.3. Virtual Tables And Shared Cache
c5: vtab.html#virtual_tables_and_shared_cache
c4:
Prior to SQLite version 3.6.17 (2009-08-10), 
the virtual table mechanism assumes 
that each database connection kept
its own copy of the database schema. Hence, the virtual table mechanism
could not be used in a database that has shared cache mode enabled. 
The sqlite3_create_module() interface would return an error if 
shared cache mode is enabled.  That restriction was relaxed
beginning with SQLite version 3.6.17.


c2: The Virtual Table Mechanism Of SQLite
c3: 1.4. Creating New Virtual Table Implementations
c5: vtab.html#creating_new_virtual_table_implementations
c4:
Follow these steps to create your own virtual table:



 Write all necessary methods.
 Create an instance of the sqlite3_module structure containing pointers
     to all the methods from step 1.
 Register your sqlite3_module structure using one of the
     sqlite3_create_module() or sqlite3_create_module_v2() interfaces.
 Run a CREATE VIRTUAL TABLE command that specifies the new module in 
     the USING clause. 


The only really hard part is step 1. You might want to start with an 
existing virtual table implementation and modify it to suit your needs.
The SQLite source tree
contains many virtual table implementations that are suitable for copying,
including:



 templatevtab.c
&rarr; A virtual table created specifically to serve as a template for
other custom virtual tables.
 series.c
&rarr; Implementation of the generate_series() table-valued function.
 json.c &rarr;
Contains the sources for the json_each() and json_tree() table-valued
functions.
 csv.c &rarr;
A virtual table that reads CSV files.



There are many other virtual table implementations
in the SQLite source tree that can be used as examples.  Locate 
these other virtual table implementations by searching 
for "sqlite3_create_module".

You might also want to implement your new virtual table as a 
loadable extension.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.1. The xCreate Method
c5: vtab.html#the_xcreate_method
c4:
int (*xCreate)(sqlite3 *db, void *pAux,
             int argc, char *const*argv,
             sqlite3_vtab **ppVTab,
             char **pzErr);


The xCreate method is called to create a new instance of a virtual table 
in response to a CREATE VIRTUAL TABLE statement.
If the xCreate method is the same pointer as the xConnect method, then the
virtual table is an eponymous virtual table.
If the xCreate method is omitted (if it is a NULL pointer) then the virtual 
table is an eponymous-only virtual table.


The db parameter is a pointer to the SQLite database connection that 
is executing the CREATE VIRTUAL TABLE statement. 
The pAux argument is the copy of the client data pointer that was the 
fourth argument to the sqlite3_create_module() or
sqlite3_create_module_v2() call that registered the 
virtual table module. 
The argv parameter is an array of argc pointers to null terminated strings. 
The first string, argv[0], is the name of the module being invoked.   The
module name is the name provided as the second argument to 
sqlite3_create_module() and as the argument to the USING clause of the
CREATE VIRTUAL TABLE statement that is running.
The second, argv[1], is the name of the database in which the new virtual 
table is being created. The database name is "main" for the primary database, or
"temp" for TEMP database, or the name given at the end of the ATTACH
statement for attached databases.  The third element of the array, argv[2], 
is the name of the new virtual table, as specified following the TABLE
keyword in the CREATE VIRTUAL TABLE statement.
If present, the fourth and subsequent strings in the argv[] array report 
the arguments to the module name in the CREATE VIRTUAL TABLE statement.

The job of this method is to construct the new virtual table object
(an sqlite3_vtab object) and return a pointer to it in *ppVTab.

As part of the task of creating a new sqlite3_vtab structure, this 
method must invoke sqlite3_declare_vtab() to tell the SQLite 
core about the columns and datatypes in the virtual table. 
The sqlite3_declare_vtab() API has the following prototype:

int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable)


The first argument to sqlite3_declare_vtab() must be the same 
database connection pointer as the first parameter to this method.
The second argument to sqlite3_declare_vtab() must a zero-terminated 
UTF-8 string that contains a well-formed CREATE TABLE statement that 
defines the columns in the virtual table and their data types. 
The name of the table in this CREATE TABLE statement is ignored, 
as are all constraints. Only the column names and datatypes matter.
The CREATE TABLE statement string need not to be 
held in persistent memory.  The string can be
deallocated and/or reused as soon as the sqlite3_declare_vtab()
routine returns.

The xConnect method can also optionally request special features
for the virtual table by making one or more calls to
the sqlite3_vtab_config() interface:

int sqlite3_vtab_config(sqlite3 *db, int op, ...);


Calls to sqlite3_vtab_config() are optional.  But for maximum
security, it is recommended that virtual table implementations
invoke "sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY)" if the
virtual table will not be used from inside of triggers or views.

The xCreate method need not initialize the pModule, nRef, and zErrMsg
fields of the sqlite3_vtab object.  The SQLite core will take care of 
that chore.

The xCreate should return SQLITE_OK if it is successful in 
creating the new virtual table, or SQLITE_ERROR if it is not successful.
If not successful, the sqlite3_vtab structure must not be allocated. 
An error message may optionally be returned in *pzErr if unsuccessful.
Space to hold the error message string must be allocated using
an SQLite memory allocation function like 
sqlite3_malloc() or sqlite3_mprintf() as the SQLite core will
attempt to free the space using sqlite3_free() after the error has
been reported up to the application.


If the xCreate method is omitted (left as a NULL pointer) then the
virtual table is an eponymous-only virtual table.  New instances of
the virtual table cannot be created using CREATE VIRTUAL TABLE and the
virtual table can only be used via its module name.
Note that SQLite versions prior to 3.9.0 (2015-10-14) do not understand
eponymous-only virtual tables and will segfault if an attempt is made
to CREATE VIRTUAL TABLE on an eponymous-only virtual table because
the xCreate method was not checked for null.


If the xCreate method is the exact same pointer as the xConnect method,
that indicates that the virtual table does not need to initialize backing
store.  Such a virtual table can be used as an eponymous virtual table
or as a named virtual table using CREATE VIRTUAL TABLE or both.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.1.1. Hidden columns in virtual tables
c5: vtab.html#hidden_columns_in_virtual_tables
c4:
If a column datatype contains the special keyword "HIDDEN"
(in any combination of upper and lower case letters) then that keyword
it is omitted from the column datatype name and the column is marked 
as a hidden column internally. 
A hidden column differs from a normal column in three respects:



 Hidden columns are not listed in the dataset returned by 
     "PRAGMA table_info",
 Hidden columns are not included in the expansion of a "*"
     expression in the result set of a SELECT, and
 Hidden columns are not included in the implicit column-list 
     used by an INSERT statement that lacks an explicit column-list. 


For example, if the following SQL is passed to sqlite3_declare_vtab():

CREATE TABLE x(a HIDDEN VARCHAR(12), b INTEGER, c INTEGER Hidden);


Then the virtual table would be created with two hidden columns,
and with datatypes of "VARCHAR(12)" and "INTEGER".

An example use of hidden columns can be seen in the FTS3 virtual 
table implementation, where every FTS virtual table
contains an FTS hidden column that is used to pass information from the
virtual table into FTS auxiliary functions and to the FTS MATCH operator.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.1.2. Table-valued functions
c5: vtab.html#table_valued_functions
c4:
A virtual table that contains hidden columns can be used like
a table-valued function in the FROM clause of a SELECT statement.
The arguments to the table-valued function become constraints on 
the HIDDEN columns of the virtual table.

For example, the "generate_series" extension (located in the
ext/misc/series.c
file in the source tree)
implements an eponymous virtual table with the following schema:

CREATE TABLE generate_series(
  value,
  start HIDDEN,
  stop HIDDEN,
  step HIDDEN
);


The sqlite3_module.xBestIndex method in the implementation of this
table checks for equality constraints against the HIDDEN columns, and uses
those as input parameters to determine the range of integer "value" outputs
to generate.  Reasonable defaults are used for any unconstrained columns.
For example, to list all integers between 5 and 50:

SELECT value FROM generate_series(5,50);


The previous query is equivalent to the following:

SELECT value FROM generate_series WHERE start=5 AND stop=50;


Arguments on the virtual table name are matched to hidden columns
in order.  The number of arguments can be less than the
number of hidden columns, in which case the latter hidden columns are
unconstrained.  However, an error results if there are more arguments
than there are hidden columns in the virtual table.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.1.3. WITHOUT ROWID Virtual Tables
c5: vtab.html#_without_rowid_virtual_tables_
c4:
Beginning with SQLite version 3.14.0 (2016-08-08), 
the CREATE TABLE statement that
is passed into sqlite3_declare_vtab() may contain a WITHOUT ROWID clause.
This is useful for cases where the virtual table rows 
cannot easily be mapped into unique integers.  A CREATE TABLE
statement that includes WITHOUT ROWID must define one or more columns as
the PRIMARY KEY.  Every column of the PRIMARY KEY must individually be
NOT NULL and all columns for each row must be collectively unique.

Note that SQLite does not enforce the PRIMARY KEY for a WITHOUT ROWID
virtual table.  Enforcement is the responsibility of the underlying
virtual table implementation.  But SQLite does assume that the PRIMARY KEY
constraint is valid - that the identified columns really are UNIQUE and
NOT NULL - and it uses that assumption to optimize queries against the
virtual table.

The rowid column is not accessible on a
WITHOUT ROWID virtual table (of course).

The xUpdate method was originally designed around having a
ROWID as a single value.  The xUpdate method has been expanded to
accommodate an arbitrary PRIMARY KEY in place of the ROWID, but the
PRIMARY KEY must still be only one column.  For this reason, SQLite
will reject any WITHOUT ROWID virtual table that has more than one
PRIMARY KEY column and a non-NULL xUpdate method.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.2. The xConnect Method
c5: vtab.html#the_xconnect_method
c4:
int (*xConnect)(sqlite3*, void *pAux,
             int argc, char *const*argv,
             sqlite3_vtab **ppVTab,
             char **pzErr);


The xConnect method is very similar to xCreate. 
It has the same parameters and constructs a new sqlite3_vtab structure 
just like xCreate. 
And it must also call sqlite3_declare_vtab() like xCreate.  It
should also make all of the same sqlite3_vtab_config() calls as
xCreate.

The difference is that xConnect is called to establish a new 
connection to an existing virtual table whereas xCreate is called 
to create a new virtual table from scratch.

The xCreate and xConnect methods are only different when the
virtual table has some kind of backing store that must be initialized 
the first time the virtual table is created. The xCreate method creates 
and initializes the backing store. The xConnect method just connects 
to an existing backing store.  When xCreate and xConnect are the same,
the table is an eponymous virtual table.

As an example, consider a virtual table implementation that 
provides read-only access to existing comma-separated-value (CSV)
files on disk. There is no backing store that needs to be created 
or initialized for such a virtual table (since the CSV files already 
exist on disk) so the xCreate and xConnect methods will be identical 
for that module.

Another example is a virtual table that implements a full-text index. 
The xCreate method must create and initialize data structures to hold 
the dictionary and posting lists for that index. The xConnect method,
on the other hand, only has to locate and use an existing dictionary 
and posting lists that were created by a prior xCreate call.

The xConnect method must return SQLITE_OK if it is successful 
in creating the new virtual table, or SQLITE_ERROR if it is not 
successful. If not successful, the sqlite3_vtab structure must not be 
allocated. An error message may optionally be returned in *pzErr if 
unsuccessful. 
Space to hold the error message string must be allocated using
an SQLite memory allocation function like 
sqlite3_malloc() or sqlite3_mprintf() as the SQLite core will
attempt to free the space using sqlite3_free() after the error has
been reported up to the application.

The xConnect method is required for every virtual table implementation, 
though the xCreate and xConnect pointers of the sqlite3_module object
may point to the same function if the virtual table does not need to
initialize backing store.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.3. The xBestIndex Method
c5: vtab.html#the_xbestindex_method
c4:
SQLite uses the xBestIndex method of a virtual table module to determine
the best way to access the virtual table. 
The xBestIndex method has a prototype like this:

int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);


The SQLite core communicates with the xBestIndex method by filling 
in certain fields of the sqlite3_index_info structure and passing a 
pointer to that structure into xBestIndex as the second parameter. 
The xBestIndex method fills out other fields of this structure which
forms the reply. The sqlite3_index_info structure looks like this:

struct sqlite3_index_info {
  /* Inputs */
  const int nConstraint;     /* Number of entries in aConstraint */
  const struct sqlite3_index_constraint {
     int iColumn;              /* Column constrained.  -1 for ROWID */
     unsigned char op;         /* Constraint operator */
     unsigned char usable;     /* True if this constraint is usable */
     int iTermOffset;          /* Used internally - xBestIndex should ignore */
  } *const aConstraint;      /* Table of WHERE clause constraints */
  const int nOrderBy;        /* Number of terms in the ORDER BY clause */
  const struct sqlite3_index_orderby {
     int iColumn;              /* Column number */
     unsigned char desc;       /* True for DESC.  False for ASC. */
  } *const aOrderBy;         /* The ORDER BY clause */

  /* Outputs */
  struct sqlite3_index_constraint_usage {
    int argvIndex;           /* if >0, constraint is part of argv to xFilter */
    unsigned char omit;      /* Do not code a test for this constraint */
  } *const aConstraintUsage;
  int idxNum;                /* Number used to identify the index */
  char *idxStr;              /* String, possibly obtained from sqlite3_malloc */
  int needToFreeIdxStr;      /* Free idxStr using sqlite3_free() if true */
  int orderByConsumed;       /* True if output is already ordered */
  double estimatedCost;      /* Estimated cost of using this index */
  /* Fields below are only available in SQLite 3.8.2 and later */
  sqlite3_int64 estimatedRows;    /* Estimated number of rows returned */
  /* Fields below are only available in SQLite 3.9.0 and later */
  int idxFlags;              /* Mask of SQLITE_INDEX_SCAN_* flags */
  /* Fields below are only available in SQLite 3.10.0 and later */
  sqlite3_uint64 colUsed;    /* Input: Mask of columns used by statement */
};


Note the warnings on the "estimatedRows", "idxFlags", and colUsed fields.
These fields were added with SQLite versions 3.8.2, 3.9.0, and 3.10.0, respectively. 
Any extension that reads or writes these fields must first check that the 
version of the SQLite library in use is greater than or equal to appropriate
version - perhaps comparing the value returned from sqlite3_libversion_number()
against constants 3008002, 3009000, and/or 3010000. The result of attempting 
to access these fields in an sqlite3_index_info structure created by an 
older version of SQLite are undefined.

In addition, there are some defined constants:

#define SQLITE_INDEX_CONSTRAINT_EQ         2
#define SQLITE_INDEX_CONSTRAINT_GT         4
#define SQLITE_INDEX_CONSTRAINT_LE         8
#define SQLITE_INDEX_CONSTRAINT_LT        16
#define SQLITE_INDEX_CONSTRAINT_GE        32
#define SQLITE_INDEX_CONSTRAINT_MATCH     64
#define SQLITE_INDEX_CONSTRAINT_LIKE      65  /* 3.10.0 and later */
#define SQLITE_INDEX_CONSTRAINT_GLOB      66  /* 3.10.0 and later */
#define SQLITE_INDEX_CONSTRAINT_REGEXP    67  /* 3.10.0 and later */
#define SQLITE_INDEX_CONSTRAINT_NE        68  /* 3.21.0 and later */
#define SQLITE_INDEX_CONSTRAINT_ISNOT     69  /* 3.21.0 and later */
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70  /* 3.21.0 and later */
#define SQLITE_INDEX_CONSTRAINT_ISNULL    71  /* 3.21.0 and later */
#define SQLITE_INDEX_CONSTRAINT_IS        72  /* 3.21.0 and later */
#define SQLITE_INDEX_CONSTRAINT_LIMIT     73  /* 3.38.0 and later */
#define SQLITE_INDEX_CONSTRAINT_OFFSET    74  /* 3.38.0 and later */
#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150  /* 3.25.0 and later */
#define SQLITE_INDEX_SCAN_UNIQUE           1  /* Scan visits at most 1 row */


Use the sqlite3_vtab_collation() interface to find the name of
the collating sequence that should be used when evaluating the i-th
constraint:

const char *sqlite3_vtab_collation(sqlite3_index_info*, int i);


The SQLite core calls the xBestIndex method when it is compiling a query
that involves a virtual table. In other words, SQLite calls this method 
when it is running sqlite3_prepare() or the equivalent. 
By calling this method, the 
SQLite core is saying to the virtual table that it needs to access 
some subset of the rows in the virtual table and it wants to know the
most efficient way to do that access. The xBestIndex method replies 
with information that the SQLite core can then use to conduct an 
efficient search of the virtual table.

While compiling a single SQL query, the SQLite core might call 
xBestIndex multiple times with different settings in sqlite3_index_info.
The SQLite core will then select the combination that appears to 
give the best performance.

Before calling this method, the SQLite core initializes an instance 
of the sqlite3_index_info structure with information about the
query that it is currently trying to process. This information 
derives mainly from the WHERE clause and ORDER BY or GROUP BY clauses 
of the query, but also from any ON or USING clauses if the query is a 
join. The information that the SQLite core provides to the xBestIndex 
method is held in the part of the structure that is marked as "Inputs". 
The "Outputs" section is initialized to zero.

The information in the sqlite3_index_info structure is ephemeral
and may be overwritten or deallocated as soon as the xBestIndex method
returns.  If the xBestIndex method needs to remember any part of the
sqlite3_index_info structure, it should make a copy.  Care must be
take to store the copy in a place where it will be deallocated, such
as in the idxStr field with needToFreeIdxStr set to 1.

Note that xBestIndex will always be called before xFilter, since
the idxNum and idxStr outputs from xBestIndex are required inputs to
xFilter.  However, there is no guarantee that xFilter will be called
following a successful xBestIndex.

The xBestIndex method is required for every virtual table implementation.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.3.1. Inputs
c5: vtab.html#inputs
c4:
The main thing that the SQLite core is trying to communicate to 
the virtual table is the constraints that are available to limit 
the number of rows that need to be searched. The aConstraint[] array 
contains one entry for each constraint. There will be exactly 
nConstraint entries in that array.

Each constraint will usually correspond to a term in the WHERE clause
or in a USING or ON clause that is of the form


     column  OP  EXPR


Where "column" is a column in the virtual table, OP is an operator 
like "=" or "&lt;", and EXPR is an arbitrary expression. So, for example,
if the WHERE clause contained a term like this:

a = 5


Then one of the constraints would be on the "a" column with 
operator "=" and an expression of "5". Constraints need not have a
literal representation of the WHERE clause. The query optimizer might
make transformations to the 
WHERE clause in order to extract as many constraints 
as it can. So, for example, if the WHERE clause contained something 
like this:

x BETWEEN 10 AND 100 AND 999&gt;y


The query optimizer might translate this into three separate constraints:

x &gt;= 10
x &lt;= 100
y &lt; 999


For each such constraint, the aConstraint[].iColumn field indicates which 
column appears on the left-hand side of the constraint.
The first column of the virtual table is column 0. 
The rowid of the virtual table is column -1. 
The aConstraint[].op field indicates which operator is used. 
The SQLITE_INDEX_CONSTRAINT_* constants map integer constants 
into operator values.
Columns occur in the order they were defined by the call to
sqlite3_declare_vtab() in the xCreate or xConnect method.
Hidden columns are counted when determining the column index.

If the xFindFunction() method for the virtual table is defined, and 
if xFindFunction() sometimes returns SQLITE_INDEX_CONSTRAINT_FUNCTION or
larger, then the constraints might also be of the form:


     FUNCTION( column, EXPR)


In this case the aConstraint[].op value is the same as the value
returned by xFindFunction() for FUNCTION.

The aConstraint[] array contains information about all constraints 
that apply to the virtual table. But some of the constraints might
not be usable because of the way tables are ordered in a join. 
The xBestIndex method must therefore only consider constraints 
that have an aConstraint[].usable flag which is true.

In addition to WHERE clause constraints, the SQLite core also 
tells the xBestIndex method about the ORDER BY clause. 
(In an aggregate query, the SQLite core might put in GROUP BY clause 
information in place of the ORDER BY clause information, but this fact
should not make any difference to the xBestIndex method.) 
If all terms of the ORDER BY clause are columns in the virtual table, 
then nOrderBy will be the number of terms in the ORDER BY clause 
and the aOrderBy[] array will identify the column for each term 
in the order by clause and whether or not that column is ASC or DESC.



In SQLite version 3.10.0 (2016-01-06) and later, 
the colUsed field is available
to indicate which fields of the virtual table are actually used by the
statement being prepared.  If the lowest bit of colUsed is set, that
means that the first column is used.  The second lowest bit corresponds
to the second column.  And so forth.  If the most significant bit of
colUsed is set, that means that one or more columns other than the 
first 63 columns are used.  If column usage information is needed by the
xFilter method, then the required bits must be encoded into either
the output idxNum field or idxStr content.

2.3.1.1. LIKE, GLOB, REGEXP, and MATCH functions

For the LIKE, GLOB, REGEXP, and MATCH operators, the 
aConstraint[].iColumn value is the virtual table column that
is the left operand of the operator.  However, if these operators
are expressed as function calls instead of operators, then
the aConstraint[].iColumn value references the virtual table
column that is the second argument to that function:


LIKE(EXPR, column)
GLOB(EXPR, column)
REGEXP(EXPR, column)
MATCH(EXPR, column)


Hence, as far as the xBestIndex() method is concerned, the following
two forms are equivalent:


column LIKE EXPR
LIKE(EXPR,column)


This special behavior of looking at the second argument of a function
only occurs for the LIKE, GLOB, REGEXP, and MATCH functions.  For all
other functions, the aConstraint[].iColumn value references the first
argument of the function.

This special feature of LIKE, GLOB, REGEXP, and MATCH does not
apply to the xFindFunction() method, however.  The
xFindFunction() method always keys off of the left operand of an
LIKE, GLOB, REGEXP, or MATCH operator but off of the first argument
to function-call equivalents of those operators.

2.3.1.2. LIMIT and OFFSET

When aConstraint[].op is one of SQLITE_INDEX_CONSTRAINT_LIMIT or
SQLITE_INDEX_CONSTRAINT_OFFSET, that indicates that there is a
LIMIT or OFFSET clause on the SQL query statement that is using
the virtual table.  The LIMIT and OFFSET operators have no
left operand, and so when aConstraint[].op is one of
SQLITE_INDEX_CONSTRAINT_LIMIT or SQLITE_INDEX_CONSTRAINT_OFFSET
then the aConstraint[].iColumn value is meaningless and should
not be used.

2.3.1.3. Right-hand side values of constraints

The sqlite3_vtab_rhs_value() interface can be used to try to
access the right-hand operand of a constraint.  However, the value
of a right-hand operator might not be known at the time that
the xBestIndex method is run, so the sqlite3_vtab_rhs_value()
call might not be successful.  Usually the right operand of a
constraint is only available to xBestIndex if it is coded as
a literal value in the input SQL.  If the right operand is
coded as an expression or a host parameter, it probably will
not be accessible to xBestIndex.  Some operators, such as
SQLITE_INDEX_CONSTRAINT_ISNULL and
SQLITE_INDEX_CONSTRAINT_ISNOTNULL have no right-hand operand.
The sqlite3_vtab_rhs_value() interface always returns
SQLITE_NOTFOUND for such operators.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.3.2. Outputs
c5: vtab.html#outputs
c4:
Given all of the information above, the job of the xBestIndex 
method it to figure out the best way to search the virtual table.

The xBestIndex method conveys an indexing strategy to the xFilter 
method through the idxNum and idxStr fields. The idxNum value and 
idxStr string content are arbitrary as far as the SQLite core is 
concerned and can have any meaning as long as xBestIndex and xFilter 
agree on what that meaning is. The SQLite core just copies the 
information from xBestIndex through to the xFilter method, assuming 
only that the char sequence referenced via idxStr is NUL terminated.

The idxStr value may be a string obtained from an SQLite
memory allocation function such as sqlite3_mprintf(). 
If this is the case, then the needToFreeIdxStr flag must be set to 
true so that the SQLite core will know to call sqlite3_free() on 
that string when it has finished with it, and thus avoid a memory leak.
The idxStr value may also be a static constant string, in which case
the needToFreeIdxStr boolean should remain false.


The estimatedCost field should be set to the estimated number
of disk access operations required to execute this query against 
the virtual table. The SQLite core will often call xBestIndex 
multiple times with different constraints, obtain multiple cost
estimates, then choose the query plan that gives the lowest estimate.
The SQLite core initializes estimatedCost to a very large value
prior to invoking xBestIndex, so if xBestIndex determines that the
current combination of parameters is undesirable, it can leave the
estimatedCost field unchanged to discourage its use.

If the current version of SQLite is 3.8.2 or greater, the estimatedRows
field may be set to an estimate of the number of rows returned by the
proposed query plan. If this value is not explicitly set, the default 
estimate of 25 rows is used.

If the current version of SQLite is 3.9.0 or greater, the idxFlags field
may be set to SQLITE_INDEX_SCAN_UNIQUE to indicate that the virtual table
will return only zero or one rows given the input constraints.  Additional
bits of the idxFlags field might be understood in later versions of SQLite.

The aConstraintUsage[] array contains one element for each of 
the nConstraint constraints in the inputs section of the 
sqlite3_index_info structure. 
The aConstraintUsage[] array is used by xBestIndex to tell the 
core how it is using the constraints.

The xBestIndex method may set aConstraintUsage[].argvIndex 
entries to values greater than zero. 
Exactly one entry should be set to 1, another to 2, another to 3, 
and so forth up to as many or as few as the xBestIndex method wants. 
The EXPR of the corresponding constraints will then be passed 
in as the argv[] parameters to xFilter.

For example, if the aConstraint[3].argvIndex is set to 1, then 
when xFilter is called, the argv[0] passed to xFilter will have 
the EXPR value of the aConstraint[3] constraint.

2.3.2.1. Omit constraint checking in bytecode

By default, the SQLite generates bytecode that will double
checks all constraints on each row of the virtual table to verify
that they are satisfied.  If the virtual table can guarantee
that a constraint will always be satisfied, it can try to
suppress that double-check by setting aConstraintUsage[].omit.
However, with some exceptions, this is only a hint and
there is no guarantee that the redundant check of the constraint
will be suppressed.  Key points:



The omit flag is only honored if the argvIndex value for the
constraint is greater than 0 and less than or equal to 16.  
Constraint checking is never suppressed for constraints
that do not pass their right operand into the xFilter method.
The current implementation is only able to suppress redundant
constraint checking for the first 16 values passed to xFilter,
though that limitation might be increased in future releases.


The omit flag is always honored for SQLITE_INDEX_CONSTRAINT_OFFSET
constraints as long as argvIndex is greater than 0.  Setting the
omit flag on an SQLITE_INDEX_CONSTRAINT_OFFSET constraint indicates
to SQLite that the virtual table will itself suppress the first N
rows of output, where N is the right operand of the OFFSET operator.
If the virtual table implementation sets omit on an
SQLITE_INDEX_CONSTRAINT_OFFSET constraint but then fails to suppress
the first N rows of output, an incorrect answer will result from
the overall query.




2.3.2.2. ORDER BY and orderByConsumed

If the virtual table will output rows in the order specified by 
the ORDER BY clause, then the orderByConsumed flag may be set to 
true. If the output is not automatically in the correct order 
then orderByConsumed must be left in its default false setting. 
This will indicate to the SQLite core that it will need to do a 
separate sorting pass over the data after it comes out of the virtual table.
Setting orderByConsumed is an optimization.  A query will always
get the correct answer if orderByConsumed is left at its default
value (0).  Unnecessary sort operations might be avoided resulting
in a faster query if orderByConsumed is set, but setting
orderByConsumed incorrectly can result in an incorrect answer.
It is suggested that new virtual table implementations leave
the orderByConsumed value unset initially, and then after everything
else is known to be working correctly, go back and attempt to
optimize by setting orderByConsumed where appropriate.

Sometimes the orderByConsumed flag can be safely set even if
the outputs from the virtual table are not strictly in the order
specified by nOrderBy and aOrderBy.  If the
sqlite3_vtab_distinct() interface returns 1 or 2, that indicates
that the ordering can be relaxed.  See the documentation on
sqlite3_vtab_distinct() for further information.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.3.3. Return Value
c5: vtab.html#return_value
c4:
The xBestIndex method should return SQLITE_OK on success.  If any
kind of fatal error occurs, an appropriate error code (ex: SQLITE_NOMEM)
should be returned instead.

If xBestIndex returns SQLITE_CONSTRAINT, that does not indicate an
error.  Rather, SQLITE_CONSTRAINT indicates that the particular combination
of input parameters specified is insufficient for the virtual table
to do its job.
This is logically the same as setting the estimatedCost to infinity.
If every call to xBestIndex for a particular query plan returns
SQLITE_CONSTRAINT, that means there is no way for the virtual table
to be safely used, and the sqlite3_prepare() call will fail with
a "no query solution" error.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.3.4. Enforcing Required Parameters On Table-Valued Functions
c5: vtab.html#enforcing_required_parameters_on_table_valued_functions
c4:
The SQLITE_CONSTRAINT return from xBestIndex
is useful for table-valued functions that
have required parameters.  If the aConstraint[].usable field is false
for one of the required parameter, then the xBestIndex method should
return SQLITE_CONSTRAINT.  If a required field does not appear in
the aConstraint[] array at all, that means that the corresponding
parameter is omitted from the input SQL.  In that case, xBestIndex
should set an error message in pVTab-&gt;zErrMsg and return
SQLITE_ERROR.  To summarize:



The aConstraint[].usable value for a required parameter is
false &rarr; return SQLITE_CONSTRAINT.

A required parameter does not appears anywhere in
the aConstraint[] array &rarr;
Set an error message in pVTab-&gt;zErrMsg and return
SQLITE_ERROR


The following example will better illustrate the use of SQLITE_CONSTRAINT
as a return value from xBestIndex:

SELECT * FROM realtab, tablevaluedfunc(realtab.x);


Assuming that the first hidden column of "tablevaluedfunc" is "param1",
the query above is semantically equivalent to this:

SELECT * FROM realtab, tablevaluedfunc
 WHERE tablevaluedfunc.param1 = realtab.x;


The query planner must decide between many possible implementations
of this query, but two plans in particular are of note:


Scan all
rows of realtab and for each row, find rows in tablevaluedfunc where
param1 is equal to realtab.x

Scan all rows of tablevalued func and for each row find rows
in realtab where x is equal to tablevaluedfunc.param1.


The xBestIndex method will be invoked once for each of the potential
plans above.  For plan 1, the aConstraint[].usable flag for the
SQLITE_CONSTRAINT_EQ constraint on the param1 column will be true because
the right-hand side value for the "param1 = ?" constraint will be known,
since it is determined by the outer realtab loop.
But for plan 2, the aConstraint[].usable flag for "param1 = ?" will be false
because the right-hand side value is determined by an inner loop and is thus
an unknown quantity.  Because param1 is a required input to the table-valued
functions, the xBestIndex method should return SQLITE_CONSTRAINT when presented 
with plan 2, indicating that a required input is missing.  This forces the
query planner to select plan 1.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.4. The xDisconnect Method
c5: vtab.html#the_xdisconnect_method
c4:
int (*xDisconnect)(sqlite3_vtab *pVTab);


This method releases a connection to a virtual table. 
Only the sqlite3_vtab object is destroyed.
The virtual table is not destroyed and any backing store 
associated with the virtual table persists. 

This method undoes the work of xConnect.

This method is a destructor for a connection to the virtual table.
Contrast this method with xDestroy.  The xDestroy is a destructor
for the entire virtual table.

The xDisconnect method is required for every virtual table implementation,
though it is acceptable for the xDisconnect and xDestroy methods to be
the same function if that makes sense for the particular virtual table.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.5. The xDestroy Method
c5: vtab.html#the_xdestroy_method
c4:
int (*xDestroy)(sqlite3_vtab *pVTab);


This method releases a connection to a virtual table, just like 
the xDisconnect method, and it also destroys the underlying 
table implementation. This method undoes the work of xCreate.

The xDisconnect method is called whenever a database connection
that uses a virtual table is closed. The xDestroy method is only 
called when a DROP TABLE statement is executed against the virtual table.

The xDestroy method is required for every virtual table implementation,
though it is acceptable for the xDisconnect and xDestroy methods to be
the same function if that makes sense for the particular virtual table.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.6. The xOpen Method
c5: vtab.html#the_xopen_method
c4:
int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);


The xOpen method creates a new cursor used for accessing (read and/or
writing) a virtual table.  A successful invocation of this method 
will allocate the memory for the sqlite3_vtab_cursor (or a subclass),
initialize the new object, and make *ppCursor point to the new object.
The successful call then returns SQLITE_OK.

For every successful call to this method, the SQLite core will
later invoke the xClose method to destroy 
the allocated cursor.

The xOpen method need not initialize the pVtab field of the
sqlite3_vtab_cursor structure.  The SQLite core will take care
of that chore automatically.

A virtual table implementation must be able to support an arbitrary
number of simultaneously open cursors.

When initially opened, the cursor is in an undefined state.
The SQLite core will invoke the xFilter method
on the cursor prior to any attempt to position or read from the cursor.

The xOpen method is required for every virtual table implementation.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.7. The xClose Method
c5: vtab.html#the_xclose_method
c4:
int (*xClose)(sqlite3_vtab_cursor*);


The xClose method closes a cursor previously opened by 
xOpen. 
The SQLite core will always call xClose once for each cursor opened 
using xOpen.

This method must release all resources allocated by the
corresponding xOpen call. The routine will not be called again even if it
returns an error.  The SQLite core will not use the
sqlite3_vtab_cursor again after it has been closed.

The xClose method is required for every virtual table implementation.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.8. The xEof Method
c5: vtab.html#the_xeof_method
c4:
int (*xEof)(sqlite3_vtab_cursor*);


The xEof method must return false (zero) if the specified cursor 
currently points to a valid row of data, or true (non-zero) otherwise. 
This method is called by the SQL engine immediately after each 
xFilter and xNext invocation.

The xEof method is required for every virtual table implementation.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.9. The xFilter Method
c5: vtab.html#the_xfilter_method
c4:
int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
              int argc, sqlite3_value **argv);


This method begins a search of a virtual table. 
The first argument is a cursor opened by xOpen. 
The next two arguments define a particular search index previously 
chosen by xBestIndex. The specific meanings of idxNum and idxStr 
are unimportant as long as xFilter and xBestIndex agree on what 
that meaning is.

The xBestIndex function may have requested the values of 
certain expressions using the aConstraintUsage[].argvIndex values 
of the sqlite3_index_info structure. 
Those values are passed to xFilter using the argc and argv parameters.

If the virtual table contains one or more rows that match the
search criteria, then the cursor must be left point at the first row.
Subsequent calls to xEof must return false (zero).
If there are no rows match, then the cursor must be left in a state 
that will cause the xEof to return true (non-zero).
The SQLite engine will use
the xColumn and xRowid methods to access that row content.
The xNext method will be used to advance to the next row.

This method must return SQLITE_OK if successful, or an sqlite 
error code if an error occurs.

The xFilter method is required for every virtual table implementation.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.10. The xNext Method
c5: vtab.html#the_xnext_method
c4:
int (*xNext)(sqlite3_vtab_cursor*);


The xNext method advances a virtual table cursor
to the next row of a result set initiated by xFilter. 
If the cursor is already pointing at the last row when this 
routine is called, then the cursor no longer points to valid 
data and a subsequent call to the xEof method must return true (non-zero). 
If the cursor is successfully advanced to another row of content, then
subsequent calls to xEof must return false (zero).

This method must return SQLITE_OK if successful, or an sqlite 
error code if an error occurs.

The xNext method is required for every virtual table implementation.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.11. The xColumn Method
c5: vtab.html#the_xcolumn_method
c4:
int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int N);


The SQLite core invokes this method in order to find the value for 
the N-th column of the current row. N is zero-based so the first column 
is numbered 0. 
The xColumn method may return its result back to SQLite using one of the
following interface:



 sqlite3_result_blob()
 sqlite3_result_double()
 sqlite3_result_int()
 sqlite3_result_int64()
 sqlite3_result_null()
 sqlite3_result_text()
 sqlite3_result_text16()
 sqlite3_result_text16le()
 sqlite3_result_text16be()
 sqlite3_result_zeroblob()



If the xColumn method implementation calls none of the functions above,
then the value of the column defaults to an SQL NULL.

To raise an error, the xColumn method should use one of the result_text() 
methods to set the error message text, then return an appropriate
error code.  The xColumn method must return SQLITE_OK on success.

The xColumn method is required for every virtual table implementation.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.12. The xRowid Method
c5: vtab.html#the_xrowid_method
c4:
int (*xRowid)(sqlite3_vtab_cursor *pCur, sqlite_int64 *pRowid);


A successful invocation of this method will cause *pRowid to be
filled with the rowid of row that the
virtual table cursor pCur is currently pointing at.
This method returns SQLITE_OK on success.
It returns an appropriate error code on failure.

The xRowid method is required for every virtual table implementation.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.13. The xUpdate Method
c5: vtab.html#the_xupdate_method
c4:
int (*xUpdate)(
  sqlite3_vtab *pVTab,
  int argc,
  sqlite3_value **argv,
  sqlite_int64 *pRowid
);


All changes to a virtual table are made using the xUpdate method.
This one method can be used to insert, delete, or update.

The argc parameter specifies the number of entries in the argv array. 
The value of argc will be 1 for a pure delete operation or N+2 for an insert
or replace or update where N is the number of columns in the table.  
In the previous sentence, N includes any hidden columns.

Every argv entry will have a non-NULL value in C but may contain the 
SQL value NULL.  In other words, it is always true that
argv&#91;i&#93;!=0 for i between 0 and argc-1.
However, it might be the case that
sqlite3_value_type(argv&#91;i&#93;)==SQLITE_NULL.

The argv[0] parameter is the rowid of a row in the virtual table 
to be deleted. If argv[0] is an SQL NULL, then no deletion occurs.

The argv[1] parameter is the rowid of a new row to be inserted 
into the virtual table. If argv[1] is an SQL NULL, then the implementation 
must choose a rowid for the newly inserted row. Subsequent argv[] 
entries contain values of the columns of the virtual table, in the 
order that the columns were declared. The number of columns will
match the table declaration that the xConnect or xCreate method made 
using the sqlite3_declare_vtab() call.  All hidden columns are included.

When doing an insert without a rowid (argc>1, argv[1] is an SQL NULL),
on a virtual table that uses ROWID (but not on a WITHOUT ROWID virtual table),
the implementation must set *pRowid to the rowid of the newly inserted row; 
this will become the value returned by the sqlite3_last_insert_rowid()
function. Setting this value in all the other cases is a harmless no-op;
the SQLite engine ignores the *pRowid return value if argc==1 or 
argv[1] is not an SQL NULL.

Each call to xUpdate will fall into one of cases shown below.
Not that references to argv&#91;i&#93; mean the SQL value
held within the argv&#91;i&#93; object, not the argv&#91;i&#93;
object itself.



argc = 1  argv[0] &ne; NULL

DELETE: The single row with rowid or PRIMARY KEY equal to argv[0] is deleted. 
No insert occurs.

argc &gt; 1  argv[0] = NULL

INSERT: A new row is inserted with column values taken from
argv[2] and following.  In a rowid virtual table, if argv[1] is an SQL NULL,
then a new unique rowid is generated automatically.  The argv[1] will be NULL
for a WITHOUT ROWID virtual table, in which case the implementation should
take the PRIMARY KEY value from the appropriate column in argv[2] and following.

argc &gt; 1  argv[0] &ne; NULL  argv[0] = argv[1]

UPDATE:
The row with rowid or PRIMARY KEY argv[0] is updated with new values 
in argv[2] and following parameters.

argc &gt; 1  argv[0] &ne; NULL  argv[0] &ne; argv[1]

UPDATE with rowid or PRIMARY KEY change:
The row with rowid or PRIMARY KEY argv[0] is updated with 
the rowid or PRIMARY KEY in argv[1] 
and new values in argv[2] and following parameters. This will occur 
when an SQL statement updates a rowid, as in the statement:

   UPDATE table SET rowid=rowid+1 WHERE ...; 




The xUpdate method must return SQLITE_OK if and only if it is
successful.  If a failure occurs, the xUpdate must return an appropriate
error code.  On a failure, the pVTab->zErrMsg element may optionally
be replaced with error message text stored in memory allocated from SQLite 
using functions such as sqlite3_mprintf() or sqlite3_malloc().

If the xUpdate method violates some constraint of the virtual table
(including, but not limited to, attempting to store a value of the wrong 
datatype, attempting to store a value that is too
large or too small, or attempting to change a read-only value) then the
xUpdate must fail with an appropriate error code.

If the xUpdate method is performing an UPDATE, then
sqlite3_value_nochange(X) can be used to discover which columns
of the virtual table were actually modified by the UPDATE
statement.  The sqlite3_value_nochange(X) interface returns
true for columns that do not change.
On every UPDATE, SQLite will first invoke
xColumn separately for each unchanging column in the table to 
obtain the value for that column.  The xColumn method can
check to see if the column is unchanged at the SQL level
by invoking sqlite3_vtab_nochange().  If xColumn sees that
the column is not being modified, it should return without setting 
a result using one of the sqlite3_result_xxxxx()
interfaces.  Only in that case sqlite3_value_nochange() will be
true within the xUpdate method.  If xColumn does
invoke one or more sqlite3_result_xxxxx()
interfaces, then SQLite understands that as a change in the value
of the column and the sqlite3_value_nochange() call for that
column within xUpdate will return false.

There might be one or more sqlite3_vtab_cursor objects open and in use 
on the virtual table instance and perhaps even on the row of the virtual
table when the xUpdate method is invoked.  The implementation of
xUpdate must be prepared for attempts to delete or modify rows of the table
out from other existing cursors.  If the virtual table cannot accommodate
such changes, the xUpdate method must return an error code.

The xUpdate method is optional.
If the xUpdate pointer in the sqlite3_module for a virtual table
is a NULL pointer, then the virtual table is read-only.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.14. The xFindFunction Method
c5: vtab.html#the_xfindfunction_method
c4:
int (*xFindFunction)(
  sqlite3_vtab *pVtab,
  int nArg,
  const char *zName,
  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
  void **ppArg
);


This method is called during sqlite3_prepare() to give the virtual
table implementation an opportunity to overload functions. 
This method may be set to NULL in which case no overloading occurs.

When a function uses a column from a virtual table as its first 
argument, this method is called to see if the virtual table would 
like to overload the function. The first three parameters are inputs: 
the virtual table, the number of arguments to the function, and the 
name of the function. If no overloading is desired, this method
returns 0. To overload the function, this method writes the new 
function implementation into *pxFunc and writes user data into *ppArg 
and returns either 1 or a number between
SQLITE_INDEX_CONSTRAINT_FUNCTION and 255.

Historically, the return value from xFindFunction() was either zero
or one.  Zero means that the function is not overloaded and one means that
it is overload.  The ability to return values of 
SQLITE_INDEX_CONSTRAINT_FUNCTION or greater was added in
version 3.25.0 (2018-09-15).  If xFindFunction returns
SQLITE_INDEX_CONSTRAINT_FUNCTION or greater, than means that the function
takes two arguments and the function
can be used as a boolean in the WHERE clause of a query and that
the virtual table is able to exploit that function to speed up the query
result.  When xFindFunction returns SQLITE_INDEX_CONSTRAINT_FUNCTION or 
larger, the value returned becomes the sqlite3_index_info.aConstraint.op
value for one of the constraints passed into xBestIndex().  The first
argument to the function is the column identified by 
aConstraint[].iColumn field of the constraint and the second argument to the
function is the value that will be passed into xFilter() (if the
aConstraintUsage[].argvIndex value is set) or the value returned from
sqlite3_vtab_rhs_value().

The Geopoly module is an example of a virtual table that makes use
of SQLITE_INDEX_CONSTRAINT_FUNCTION to improve performance.
The xFindFunction() method for Geopoly returns
SQLITE_INDEX_CONSTRAINT_FUNCTION for the geopoly_overlap() SQL function
and it returns
SQLITE_INDEX_CONSTRAINT_FUNCTION+1 for the geopoly_within() SQL function.
This permits search optimizations for queries such as:

SELECT * FROM geopolytab WHERE geopoly_overlap(_shape, $query_polygon);
SELECT * FROM geopolytab WHERE geopoly_within(_shape, $query_polygon);


Note that infix functions (LIKE, GLOB, REGEXP, and MATCH) reverse 
the order of their arguments. So "like(A,B)" would normally work the same
as "B like A".
However, xFindFunction() always looks a the left-most argument, not
the first logical argument.
Hence, for the form "B like A", SQLite looks at the
left operand "B" and if that operand is a virtual table column
it invokes the xFindFunction() method on that virtual table.
But if the form "like(A,B)" is used instead, then SQLite checks
the A term to see if it is column of a virtual table and if so
it invokes the xFindFunction() method for the virtual table of
column A. 

The function pointer returned by this routine must be valid for
the lifetime of the sqlite3_vtab object given in the first parameter.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.15. The xBegin Method
c5: vtab.html#the_xbegin_method
c4:
int (*xBegin)(sqlite3_vtab *pVTab);


This method begins a transaction on a virtual table.
This is method is optional.  The xBegin pointer of sqlite3_module
may be NULL.

This method is always followed by one call to either the
xCommit or xRollback method.  Virtual table transactions do
not nest, so the xBegin method will not be invoked more than once
on a single virtual table
without an intervening call to either xCommit or xRollback.
Multiple calls to other methods can and likely will occur in between
the xBegin and the corresponding xCommit or xRollback.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.16. The xSync Method
c5: vtab.html#the_xsync_method
c4:
int (*xSync)(sqlite3_vtab *pVTab);



This method signals the start of a two-phase commit on a virtual
table.
This is method is optional.  The xSync pointer of sqlite3_module
may be NULL.

This method is only invoked after call to the xBegin method and
prior to an xCommit or xRollback.  In order to implement two-phase
commit, the xSync method on all virtual tables is invoked prior to
invoking the xCommit method on any virtual table.  If any of the 
xSync methods fail, the entire transaction is rolled back.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.17. The xCommit Method
c5: vtab.html#the_xcommit_method
c4:
int (*xCommit)(sqlite3_vtab *pVTab);


This method causes a virtual table transaction to commit.
This is method is optional.  The xCommit pointer of sqlite3_module
may be NULL.

A call to this method always follows a prior call to xBegin and
xSync.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.18. The xRollback Method
c5: vtab.html#the_xrollback_method
c4:
int (*xRollback)(sqlite3_vtab *pVTab);


This method causes a virtual table transaction to rollback.
This is method is optional.  The xRollback pointer of sqlite3_module
may be NULL.

A call to this method always follows a prior call to xBegin.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.19. The xRename Method
c5: vtab.html#the_xrename_method
c4:
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);


This method provides notification that the virtual table implementation
that the virtual table will be given a new name. 
If this method returns SQLITE_OK then SQLite renames the table.
If this method returns an error code then the renaming is prevented.

The xRename method is optional.  If omitted, then the virtual
table may not be renamed using the ALTER TABLE RENAME command.

The PRAGMA legacy_alter_table setting is enabled prior to invoking this
method, and the value for legacy_alter_table is restored after this
method finishes.  This is necessary for the correct operation of virtual
tables that make use of shadow tables where the shadow tables must be
renamed to match the new virtual table name.  If the legacy_alter_format is
off, then the xConnect method will be invoked for the virtual table every
time the xRename method tries to change the name of the shadow table.


c2: The Virtual Table Mechanism Of SQLite
c3: 2.20. The xSavepoint, xRelease, and xRollbackTo Methods
c5: vtab.html#the_xsavepoint_xrelease_and_xrollbackto_methods
c4:
int (*xSavepoint)(sqlite3_vtab *pVtab, int);
int (*xRelease)(sqlite3_vtab *pVtab, int);
int (*xRollbackTo)(sqlite3_vtab *pVtab, int);



These methods provide the virtual table implementation an opportunity to
implement nested transactions.  They are always optional and will only be
called in SQLite version 3.7.7 (2011-06-23) and later.



When xSavepoint(X,N) is invoked, that is a signal to the virtual table X
that it should save its current state as savepoint N.  
A subsequent call
to xRollbackTo(X,R) means that the state of the virtual table should return
to what it was when xSavepoint(X,R) was last called.  
The call
to xRollbackTo(X,R) will invalidate all savepoints with N>R; none of the
invalided savepoints will be rolled back or released without first
being reinitialized by a call to xSavepoint().  
A call to xRelease(X,M) invalidates all savepoints where N>=M.



None of the xSavepoint(), xRelease(), or xRollbackTo() methods will ever
be called except in between calls to xBegin() and 
either xCommit() or xRollback().


c2: The Virtual Table Mechanism Of SQLite
c3: 2.21. The xShadowName Method
c5: vtab.html#the_xshadowname_method
c4:
Some virtual table implementations (ex: FTS3, FTS5, and RTREE) make
use of real (non-virtual) database tables to store content.  For example,
when content is inserted into the FTS3 virtual table, the data is ultimately
stored in real tables named "%_content", "%_segdir", "%_segments", "%_stat",
and "%_docsize" where "%" is the name of the original virtual table.  This
auxiliary real tables that store content for a virtual table are called
"shadow tables".  See
(1),
(2), and
(3) for additional information.

The xShadowName method exists to allow SQLite to determine whether a
certain real table is in fact a shadow table for a virtual table.

SQLite understands a real table to be a shadow table if all of
the following are true:


 The name of the table contains one or more "_" characters.
 The part of the name prior to the last "_" exactly matches
     the name of a virtual table that was created using CREATE VIRTUAL TABLE.
     (Shadow tables are not recognized for eponymous virtual tables
     and table-valued functions.)
 The virtual table contains an xShadowName method.
 The xShadowName method returns true when its input is the part
     of the table name past the last "_" character.



If SQLite recognizes a table as a shadow table, and if the
SQLITE_DBCONFIG_DEFENSIVE flag is set, then the shadow table is read-only
for ordinary SQL statements.  The shadow table can still be written, but
only by SQL that is invoked from within one of the methods of
some virtual table implementation.


The whole point of the xShadowName method is to protect the content of
shadow tables from being corrupted by hostile SQL.  Every virtual table
implementation that uses shadow tables should be able to detect and cope
with corrupted shadow table content.  However, bugs in particular virtual 
table implementation might allow a deliberately corrupted shadow table to
cause a crash or other malfunction.  The xShadowName mechanism seeks to 
avoid zero-day exploits by preventing ordinary SQL statements from
deliberately corrupting shadow tables.


Shadow tables are read/write by default.
Shadow tables only become read-only when the SQLITE_DBCONFIG_DEFENSIVE
flag is set using sqlite3_db_config().
Shadow tables need to be read/write by default in order to maintain
backwards compatibility.
For example, the SQL text generated by the .dump command of the CLI
writes directly into shadow tables.
This page last modified on  2022-12-05 12:38:46 UTC


c2: The SQLITE_DBPAGE Virtual Table
c3: 1. Overview
c5: dbpage.html#overview
c4:
The SQLITE_DBPAGE extension implements an eponymous-only virtual table that
provides direct access to the underlying database file by interacting
with the pager.  SQLITE_DBPAGE is capable of both reading and writing any
page of the database.  Because interaction is through the pager layer, all
changes are transactional.



Warning: writing to the SQLITE_DBPAGE virtual table can very easily
cause unrecoverably database corruption.  Do not allow untrusted components
to access the SQLITE_DBPAGE table.  Use appropriate care while using the
SQLITE_DBPAGE table.  Back up important data prior to experimenting with the
SQLITE_DBPAGE table.  Writes to the SQLITE_DBPAGE virtual table are
disabled when the SQLITE_DBCONFIG_DEFENSIVE flag is set.


The SQLITE_DBPAGE extension is included in the amalgamation though 
it is disabled
by default.  Use the SQLITE_ENABLE_DBPAGE_VTAB compile-time option to enable
the SQLITE_DBPAGE extension.  The SQLITE_DBPAGE extension makes use of
unpublished internal interfaces and is not run-time loadable.  The only way
to add SQLITE_DBPAGE to an application is to compile it in using the
SQLITE_ENABLE_DBPAGE_VTAB compile-time option.



The SQLITE_DBPAGE extension is enabled in default builds
of the command-line shell.


c2: The SQLITE_DBPAGE Virtual Table
c3: 2. Usage
c5: dbpage.html#usage
c4:
The SQLITE_DBPAGE virtual table read/write table that provides direct
access to the underlying disk file on a page-by-page basis.  The
virtual table appears to have a schema like this:

CREATE TABLE sqlite_dbpage(
  pgno INTEGER PRIMARY KEY,
  data BLOB
);



An SQLite database file is divided into pages.
The first page is 1, the second page is 2, and so forth.
There is no page 0.
Every page is the same size.
The size of every page is a power of 2 between 512 and 65536.
See the file format documentation for further details.


The SQLITE_DBPAGE table allows an application to view or replace the
raw binary content of each page of the database file.
No attempt is made to interpret the content of the page.
Content is returned byte-for-byte as it appears on disk.


The SQLITE_DBPAGE table has one row for each page in the database file.
SQLITE_DBPAGE allows pages to be read or to be overwritten.
However the size of the database file cannot be changed.  It is not
possible to change the number of rows in the SQLITE_DBPAGE table by
running DELETE or INSERT operations against that table.


c2: The SQLITE_DBPAGE Virtual Table
c3: 2.1. Using SQLITE_DBPAGE On ATTACH-ed Databases
c5: dbpage.html#using_sqlite_dbpage_on_attach_ed_databases
c4:
The SQLITE_DBPAGE table schema shown above is incomplete.  There is
a third hidden column named "schema" that determines which
ATTACH-ed database should be read or written.  Because
the "schema" column is hidden, it can be used as a parameter when
SQLITE_DBPAGE is invoked as a table-valued function.


For example, suppose an additional database is attached to the 
database connection using a statement like this:

ATTACH 'auxdata1.db' AS aux1;



Then to read the first page of that database file, one merely runs:

SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=1;



If the "schema" is omitted, it defaults to the primary database
(usually called 'main', unless renamed using SQLITE_DBCONFIG_MAINDBNAME).
Hence, the following two queries are normally equivalent:

SELECT data FROM sqlite_dbpage('main') WHERE pgno=1;
SELECT data FROM sqlite_dbpage WHERE pgno=1;



The SQLITE_DBPAGE table can participate in a join just like any other
table.  Hence, to see the content of the first page to all connected
database files, one might run a statement like this:

SELECT dbpage.data, dblist.name
  FROM pragma_database_list AS dblist
  JOIN sqlite_dbpage(dblist.name) AS dbpage
 WHERE dbpage.pgno=1;

This page last modified on  2018-11-12 15:24:40 UTC


c2: STRICT Tables
c3: 1. Introduction
c5: stricttables.html#introduction
c4:
SQLite strives to be flexible regarding the datatype of
the content that it stores.  For example, if a table column has a type of
"INTEGER", then SQLite tries to convert anything inserted into that column
into an integer.  So an attempt to insert the string '123' results
in an integer 123 being inserted.  But if the content cannot be losslessly
converted into an integer, for example if the input is 'xyz', then
the original string is inserted instead.
See the Datatypes In SQLite document for additional information.

Some developers appreciate the freedom that SQLite's flexible typing
rules provide and use that freedom to advantage.
But other developers are aghast at SQLite's
flagrant rule-breaking and prefer the traditional rigid type
system found in all other SQL database engines and in the
SQL standard.  For this latter group, SQLite supports a strict typing
mode, as of version 3.37.0 (2021-11-27), that is enabled
separately for each table.


c2: STRICT Tables
c3: 2. STRICT Tables
c5: stricttables.html#strict_tables
c4:
In a CREATE TABLE statement, if the "STRICT" table-option keyword is
added to the end, after the closing ")", then strict typing rules apply
to that table. 
The STRICT keyword causes the following differences:



Every column definition must specify a datatype for that column.
The freedom to specify a column without a datatype is removed.


The datatype must be one of following:

 INT
 INTEGER
 REAL
 TEXT
 BLOB
 ANY

No other datatype names are allowed, though new types might be added in
future releases of SQLite.


Content inserted into the column with a datatype other than ANY
must be either a NULL (assuming there
is no NOT NULL constraint on the column) or the type specified.
SQLite attempts to coerce the data into the appropriate type using the usual
affinity rules, as PostgreSQL, MySQL, SQL Server,
and Oracle all do.  If the value cannot be
losslessly converted in the specified datatype, then an
SQLITE_CONSTRAINT_DATATYPE error is raised.


Columns with datatype ANY can accept any kind of data (except they will
reject NULL values if they have a NOT NULL constraint, of course).  No
type coercion occurs for a column of type ANY in a STRICT table.


Columns that are part of the PRIMARY KEY are implicitly NOT NULL.
However, even though the PRIMARY KEY has an implicit NOT NULL constraint,
when a NULL value is inserted into an INTEGER PRIMARY KEY column, the
NULL is automatically converted into a unique integer, using the same
rules for INTEGER PRIMARY KEY on ordinary, non-strict tables.


The PRAGMA integrity_check and PRAGMA quick_check commands check the
type of the content of all columns in STRICT tables and show errors if
anything is amiss.



Everything else about a STRICT table works the same as it does in an
ordinary non-strict table:


 CHECK constraints work the same.
 NOT NULL constraints work the same.
 FOREIGN KEY constraints work the same.
 UNIQUE constraints work the same.
 DEFAULT clauses work the same.
 COLLATE clauses work the same.
 Generated columns work the same.
 ON CONFLICT clauses work the same.
 Indexes work the same.
 AUTOINCREMENT works the same.
 An INTEGER PRIMARY KEY column is an alias for the rowid, but an
INT PRIMARY KEY column is not.
 The on-disk format for the table data is the same.


c2: STRICT Tables
c3: 3. The ANY datatype
c5: stricttables.html#the_any_datatype
c4:
The ability to host any type of data in a single column has proven to
be remarkably useful over the years.  In order to continue supporting this
ability, even in STRICT tables, the new ANY datatype name is introduced.
When the datatype of a column is "ANY", that means that any kind of data - 
integers, floating point values, strings, or binary blobs, can be inserted
into that table and its value and datatype will be preserved exactly as
it is inserted.  As far as we know, SQLite is the only SQL database engine
that supports this advanced capability.

The behavior of ANY is slightly different in a
STRICT table versus an ordinary non-strict table.  In a STRICT table,
a column of type ANY always preserves the data exactly as it is received.
For an ordinary non-strict table, a column of type ANY will attempt to
convert strings that look like numbers into a numeric value, and if
successful will store the numeric value rather than the original string.
For example:



STRICTordinary non-strict
CREATE TABLE t1(a ANY) STRICT;
INSERT INTO t1 VALUES('000123');
SELECT typeof(a), quote(a) FROM t1;
-- result: text '000123'

CREATE TABLE t1(a ANY);
INSERT INTO t1 VALUES('000123');
SELECT typeof(a), quote(a) FROM t1;
-- result: integer 123


c2: STRICT Tables
c3: 4. Backwards Compatibility
c5: stricttables.html#backwards_compatibility
c4:
The STRICT keyword at the end of a CREATE TABLE statement is only
recognized by SQLite version 3.37.0 (2021-11-27) and later.  If
you try to open a database containing the STRICT keyword in an earlier
version of SQLite, it will not recognize the keyword and will report
an error (except as noted below).  But apart from the extra STRICT keyword,
the underlying file format of the database is identical.

Thus, in general, a database file that contains one or more STRICT
tables can only be read and written by SQLite version 3.37.0 or later.
However, a database created by SQLite 3.37.0 or later can still be
read and written by earlier versions of SQLite, going all the way back
to version 3.0.0 (2004-06-18) as long as the database does not contain
any STRICT tables or other features that were introduced after the older
version of SQLite.

The STRICT keyword may still be used as an identifier.
(It is only treated as a keyword in a certain part of the syntax,
and sqlite3_keyword_check(..) does not recognize it as a regular keyword.)


c2: STRICT Tables
c3: 4.1. Accessing STRICT tables in earlier versions of SQLite
c5: stricttables.html#accessing_strict_tables_in_earlier_versions_of_sqlite
c4:
Because of a quirk in the SQL language parser, versions of SQLite prior
to 3.37.0 can still read and write STRICT tables if they set
"PRAGMA writable_schema=ON" immediately after opening the database
file, prior to doing anything else that requires knowing the schema.
One of the features of PRAGMA writable_schema=ON is that it disables
errors in the schema parser.  This is intentional, because a big reason for
having PRAGMA writable_schema=ON is to facilitate recovery of database files
with corrupt schemas.  So with writable_schema=ON, when the schema
parser reaches the STRICT keyword, it says to itself "I don't know what
to do with this, but everything up to this point seems like a valid
table definition so I'll just use what I have."  Hence, the STRICT
keyword is effectively ignored.  Because nothing else about the file
format changes for STRICT tables, everything else will work normally.
Of course, rigid type enforcement will not occur because the earlier
versions of SQLite do not know how to do that.

The .dump command in the CLI sets PRAGMA writable_schema=ON, because
.dump is designed to extract as much content as it can even from a corrupt
database file.  Hence, if you are using an older version of SQLite and
you open a database with STRICT tables in the CLI and issue the ".dump"
command before doing anything else, you will be able to read and write
to the STRICT tables without rigid type enforcement.  This could, potentially,
corrupt the database, by allowing incorrect types into STRICT tables.
Reopening the database with a newer version of SQLite and running
"PRAGMA quick_check" will detect and report all such corruption.


c2: STRICT Tables
c3: 5. Other Table Options
c5: stricttables.html#other_table_options
c4:
The SQLite parser accepts a comma-separated list of table options after
the final close parenthesis in a CREATE TABLE statement.  As of this
writing (2021-08-23) only two options are recognized:


 STRICT
 WITHOUT ROWID


If there are multiple options, they can be specified in any order.
To keep things simple, the current parser accepts duplicate options without
complaining, but that might change in future releases, so applications
should not rely on it.
This page last modified on  2022-01-20 21:38:08 UTC


c2: Invalid UTF Policy
c3: 1. Garbage In, Garbage Out
c5: invalidutf.html#garbage_in_garbage_out
c4:
With regard to invalid UTF, SQLite follows a policy of
Garbage-In, Garbage-Out (GIGO). If you insert invalid UTF
into an SQLite database, then try to query that data, what you get back out
might not be exactly what you put in.  If you put garbage in, then you
may not complain if you get different garbage back out.


For the purposes of this discussion, "invalid UTF" can mean any of
the following circumstances:



Invalid surrogate pairs in UTF-16.


Invalid multi-byte sequences in UTF-8.


Using more bytes of UTF-8 than necessary to represent a single
code point.  (Example:  encoding 'A' as the two-byte sequence
0xc1, 0x01 instead of just a single 0x41 byte.)


NUL characters (U+0000) embedded in strings.


Invalid sequences of combining characters.


UTF-8 or UTF-16 bytes sequences that encode numbers that are not
defined Unicode characters.


c2: Invalid UTF Policy
c3: 1.1. Invalid UTF will never cause memory errors
c5: invalidutf.html#invalid_utf_will_never_cause_memory_errors
c4:
If you insert invalid UTF into an SQLite database, then SQLite makes
no guarantees about what text you might get back out.  But it does
promise that invalid UTF will never cause memory errors
(array overruns, reads or writes of uninitialized memory, etc), at
least for the built-in processing of SQLite.
In other words, invalid UTF will not cause SQLite to crash.


This promise only applies to the core SQLite components, not
application-provided extensions, of course.
If an application adds new application-defined SQL functions or
virtual tables or collating sequences or other extensions, and a
database contains invalid UTF, then invalid UTF might get passed
into those extensions.  If the invalid UTF causes one of those
extensions to crash, then that is a problem with the extension,
not with SQLite.


c2: Invalid UTF Policy
c3: 2. No enforcement of text formatting rules
c5: invalidutf.html#no_enforcement_of_text_formatting_rules
c4:
SQLite does not try to enforce UTF formatting rules.  You can
insert invalid UTF into a TEXT field and SQLite will not complain
about this.  It stores the invalid TEXT as best it can.  SQLite
sees its role in the world as a storage engine, not a text format
validation engine.


c2: Invalid UTF Policy
c3: 3. Best effort to preserve text
c5: invalidutf.html#best_effort_to_preserve_text
c4:
SQLite does not promise to always preserve invalid UTF, but it does
make an effort.  Generally speaking, if you insert invalid UTF into
SQLite, you will get the exact same byte sequence back out, as long
as you do not ask SQLite to transform the text in any way.


For example, if you insert some UTF-16LE with invalid surrogates into
a TEXT column of a table of a database that has PRAGMA encoding=UTF16LE,
then later query that column using sqlite3_column_text16(), you will 
probably get back the same exact invalid UTF-16.  But if you insert the
same invalid UTF-16LE content in a PRAGMA encoding=UTF8 database,
the content must be converted into UTF8 when it is stored, which could
cause irreversible changes to the content.  Or if you insert that
same invalid UTF-16LE content into a PRAGMA encoding=UTF16LE database
but then read it out using sqlite3_column_text(), then a UTF16 to
UTF8 conversion must occur during the read-out and that conversion might
introduce irreversible changes.


Or, suppose you are doing everything using UTF-8 (the most common case).
Invalid UTF-8 will normally pass through the database without any change
in its byte sequence.  However, if you try to transform the invalid
UTF-8 with SQL function like substr() or replace()
or if you try to do string matching with the LIKE operator, then
you might get unexpected results.


So, in other words, SQLite does not actively try to subvert your
invalid text.  But when you ask SQLite to make transformations of invalid
UTF, there are no guarantees that those transformations will be reversible
or even sensible.
This page last modified on  2021-12-13 15:03:51 UTC


c2: How SQLite Works
c3: 1. Background
c5: howitworks.html#background
c4:
SQLite is a software library
that translates high-level disk I/O requests generated by an application
into low-level I/O operations that
can be carried out by the operating system.  The application constructs 
high-level I/O requests using the
SQL language.
SQLite translates each high-level SQL statement into a sequence of
many low-level I/O requests (open a file, read a few bytes from a file,
write a few bytes into a file, etc.) that do the work requested by
the SQL.



An application program could do all its disk I/O by direct calls to
operating system I/O routines
or by using a key/value storage engine like 
Berkeley DB or
RocksDB (to name but two).
But there are advantages to using a higher-level interface based
on the SQL language.



SQL is a very high-level language.
A few lines of SQL can replace hundreds or thousands of lines of
procedural code.  SQL thus reduces
the amount of work needed to develop and maintain the application,
and thereby helps to reduce the number of bugs in the application.


SQL and SQLite are 
transactional.
The use of a transactional storage system makes it much easier to
reason about the behavior of the application, and to write applications
that are robust, even in the face of software bugs, hardware faults,
or power losses.


SQLite is often
faster than direct low-level I/O.
This is counterintuitive.  One would expect that a
high-level interface such as SQLite would impose a run-time penalty.
And, theoretically, that is correct.  But in practice, SQL-based
systems such as SQLite do so many behind-the-scenes optimizations
that an application developer would never have time to create and
maintain, that the SQL-based systems end up providing
a net performance gain.


c2: How SQLite Works
c3: 1.1. SQLite Is Different From Most Other SQL Databases
c5: howitworks.html#sqlite_is_different_from_most_other_sql_databases
c4:
There are many SQL-based database management systems available, besides
SQLite.  Common options include MySQL, PostgreSQL, and SQL-Server.
All these systems use the SQL langauge to communicate with the 
application, just like SQLite.  But these other systems different
from SQLite in important respects.



SQLite is a serverless software library, whereas the other
systems are client-server based.  With MySQL, PostgreSQL, SQL-Server,
and others, the application sends a message containing some SQL
over to a separate server thread or process. That separate
thread or process performs the requested I/O, then send the results
back to the application.  But there is no separate thread or
process with SQLite.  SQLite runs in the same address space as
the application, using the same program counter and heap storage.
SQLite does no interprocess communication (IPC).  When an application
sends an SQL statement into SQLite (by invoking a the appropriate
SQLite library subroutine), SQLite interprets the SQL
in the same thread as the caller.  When an SQLite API routine
returns, it does not leave behind any background tasks that
run separately from the application.


An SQLite database is a single ordinary file on disk
(with a well-defined file format).  With other
systems, a "database" is usually a large number of separate
files hidden away in obscure directories of the filesystem, or
even spread across multiple machines.  But with SQLite, a
complete database is just an ordinary disk file.


c2: How SQLite Works
c3: 2. SQL Is A Programming Language
c5: howitworks.html#sql_is_a_programming_language
c4:
The best way to understand how SQL database engines work is to
think of SQL as a programming language, not as a "query language".
Each SQL statement is a separate program.  Applications construct
SQL program source files and send them to the database engine.
The database engine compiles the SQL source code into executable
form, runs that executable, then sends the result back to the
application.


While SQL is a programming language, it is different from other
programming languages like C, Javascript, Python, or Go in that
SQL is a 
declarative language
where the others are
imperative languages.
This is an important difference that has implications for the
design of the compiler used to translate program source text into an
executable format. However, those details 
should not detract from the fact that
SQL is really just another programming language.


c2: How SQLite Works
c3: 2.1. Programming Language Processing Steps
c5: howitworks.html#programming_language_processing_steps
c4:
All programming languages are processed in two steps:



Translate the program source text into an executable format.

Run the executable generated in the previous step in order to
carry out the desired action.



All programming languages uses those two basic steps.
The main difference is in the executable format.


"Compiled" languages like C++ and Rust translate
the source text into machine code that can be directly executed
by the underlying hardware.  There exist SQL database systems
that do the same with SQL - they translate each SQL statement
directly into machine code.  But that approach is uncommon and
is not the approach taken by SQLite.


Other languages like Java, Perl, Python, and TCL
typically translate the program source text into bytecode.
This bytecode is then run through an interpreter that
reads the bytecode and carries out the desired operations.
SQLite uses this bytecode approach.  If you preceed
any SQL statement with the "EXPLAIN" keyword in SQLite,
it will show you the bytecode that is generated rather
than run the bytecode.


Another approach is to translate the program source text
into a tree of objects in memory.  This tree is the "executable".
An interpret runs the executable by walking the tree.
This is the technique used by MySQL, PostgreSQL, and
SQL-Server.


Of course, not every language fits neatly into one of the
above categories.  This applies to both SQL database engines
and more familiar imperative programming languages.  Javascript
is famous for using a hybrid execution model, where the code
is initially compiled into a tree of objects, but might be
further translating (using just-in-time compilation) down into
more efficient bytecode or machine code, as a means of boosting
performance.


The executable format really ends up being just an implementation
detail.  The key point is that all languages have a compiler
step which translates programs into an executable format and
a run step that executes the compiled program.


c2: How SQLite Works
c3: 2.2. Compiling SQLite Programs
c5: howitworks.html#compiling_sqlite_programs
c4:
When an SQL program is submitted to SQLite, the first step is
to split the source text into "tokens".  A token might be:


A language keyword like "SELECT" or "UPDATE".
An identifier for a table or column or variable.
Punctuation characters like "," or "==" or ";".
Literal values: numeric or string constants.
Whitespace or comments.



Whitespace and comment tokens are discarded.  All other tokens
are fed into an
LALR(1) Parser
that analyzes the structure of the input program and generates an
Abstract Syntax Tree (AST)
for the input program.


The parser forwards the AST on to the code generator.
The code generator is the heart of SQLite, and is where most of
the magic happens.
The code generator resolves symbolic names in the AST - matching
the names of columns and tables in the input SQL into actual
columns and tables of the database.  The code generator also does
various transformations on the AST to "optimize" it.  Finally
the code generator chooses appropriate algorithms to implement
the operations requested by the AST and constructs bytecode to
carry out those operations.


The bytecode generated by the code generator is called a
"prepared statement".  Translating SQL source text into a
prepared statement is analogous to converting a C++ program
into machine code by invoking gcc or clang.  Human-readable
source text (SQL or C++) goes in, and a machine readable executable
(bytecode or machine code) comes out.


c2: How SQLite Works
c3: 3. Further Reading
c5: howitworks.html#further_reading
c4:
The Atomic Commit document describes how SQLite implements
transactions.


The bytecode engine document has more information
on the bytecode format used by SQLite, and how to view and interpret
an SQLite prepared statement.


The SQLite query planner and
Next Generation Query Planner documents have further details
on the algorithms SQLite uses to implement SQL statements and
how it goes above choosing an appropriate algorithm for each
individual SQL statement.

This page last modified on  2022-06-16 15:42:19 UTC


c2: WAL-mode File Format
c5: walformat.html#
c4:
This document describes low-level details on how WAL mode is
implemented on unix and windows.

The separate file format description provides details on the
structure of a database file and of the write-head log file used in
WAL mode.  But details of the locking protocol and of the format
of the WAL-index are deliberately omitted since those details
are left to discretion of individual VFS implementations.  This
document fills in those missing details for the unix and windows VFSes.

For completeness, some of the higher level formatting information
contains in the file format document and elsewhere is replicated here,
when it pertains to WAL mode processing.


c2: WAL-mode File Format
c3: 1. Files On Disk
c5: walformat.html#files_on_disk
c4:
When in active use, the state of a WAL mode database is described
by three separate files:


 The main database file with an arbitrary name "X".
 The write-ahead log file, usually named "X-wal".
 The wal-index file, usually named "X-shm".


c2: WAL-mode File Format
c3: 1.1. The Main Database File
c5: walformat.html#the_main_database_file
c4:
The format of the main database file is as described in the
file format document.  The file format version numbers at offsets
18 and 19 into the main database must both be 2 to indicate that the
database is in WAL mode.  The main database may have an arbitrary
name allowed by the underlying filesystem.  No special file suffixes
are required, though ".db", ".sqlite", and ".sqlite3" seem to be
popular choices.


c2: WAL-mode File Format
c3: 1.2. The Write-Ahead-Log or "-wal" File
c5: walformat.html#the_write_ahead_log_or_wal_file
c4:
The write-ahead log or "wal" file is a roll-forward journal
that records transactions that have been committed but not yet applied
to the main database.  Details on the format of the wal file are
describe in the WAL format subsection of the main file format
document.  The wal file is named by appending the four characters
"-wal" to the end of the name of the main database file.  Except
on 8+3 filesystems, such names are not allowed, and in that case
the file suffix is changed to ".WAL".  But as 8+3 filesystems are
increasingly rare, that exceptional case can usually be ignored.


c2: WAL-mode File Format
c3: 1.3. The Wal-Index or "-shm" file
c5: walformat.html#the_wal_index_or_shm_file
c4:
The wal-index file or "shm" file is not actually used as a file.
Rather, individual database clients mmap the shm file and use it
as shared memory for coordinating access to the database and as a cache
for quickly locating frame within the wal file.  The name
of the shm file is the main database file name with the four characters
"-shm" appended.  Or, for 8+3 filesystems, the shm file is the main
database file with the suffix changed to ".SHM".

The shm does not contain any database content and is not required
to recover the database following a crash.  For that reason, the first
client to connect to a quiescent database will normally truncate the
shm file if it exists.  Since the content of the shm file does not need
to be preserved across a crash, the shm file is never fsync()-ed to disk.
In fact, if there were a mechanism by which SQLite could tell the 
operating system to never persist the shm file to disk but always hold
it in cache memory, SQLite would use that mechanism to avoid any
unnecessary disk I/O associated with the shm file.  However, no such
mechanism exists in standard posix.

Because the shm is only used to coordinate access between concurrent
clients, the shm file is omitted if exclusive locking mode
is set, as an optimization.  When exclusive locking mode is set,
SQLite uses heap memory in place of the memory-mapped shm file.


c2: WAL-mode File Format
c3: 1.4. File Lifecycles
c5: walformat.html#file_lifecycles
c4:
When a WAL mode database is in active use, all three of the above
files usually exist.  Except, the Wal-Index file is omitted if
exclusive locking mode is set.

If the last client using the database shuts down cleanly by
calling sqlite3_close(), then a checkpoint is run automatically
in order to transfer all information from the wal file
over into the main database, and both the shm file
and the wal file are unlinked.  Thus, when the database is not in
use by any client, it is usually the case that only the main
database file exists on disk.
However, if the last client did not call sqlite3_close() before it
shut down, or if the last client to disconnect was a read-only client,
then the final cleanup operation does not occur and the
shm and wal files may still exist on disk even when the database is
not in use.


c2: WAL-mode File Format
c3: 1.5. Variations
c5: walformat.html#variations
c4:
When PRAGMA locking_mode=EXCLUSIVE (exclusive locking mode) is set,
only a single client is allowed to have the database open at one time.  Since
only a single client can use the database, the shm file is omitted.
The single client uses a buffer in heap memory as a substitute for the
memory-mapped shm file.

If a read/write client invokes
sqlite3_file_control(SQLITE_FCNTL_PERSIST_WAL) prior to shutdown,
then at shutdown a checkpoint is still run, but the shm file and wal
file are not deleted.
This allows subsequent read-only clients to connect to and read the
database.


c2: WAL-mode File Format
c3: 2. The WAL-Index File Format
c5: walformat.html#the_wal_index_file_format
c4:
The WAL-index or "shm" file is used to coordinate access to the database
by multiple clients, and as a cache to help clients quickly locate frames
within the wal file.


Because the shm file is not involved in recovery, the shm file does not
need to be machine byte-order independent.  Hence, numeric values in
the shm file are written in the native byte order of the host computer,
rather than being converted into a specific cross-platform byte order as
is done with the main database file and the wal file.


The shm file consists of one or more hash tables, where each hash table
is 32768 bytes in size.  Except, a 136-byte header is carved out of the
front of the very first hash table, so the first hash table is only
32632 bytes in size.  The total size of the shm file is always a multiple
of 32768.  In most cases, the total size of the shm file is exactly 32768
bytes.  The shm file only needs to grow beyond a single hash table if
when the wal file grows very large (more than 4079 frames).  Since the
default automatic checkpoint threshold is
1000, WAL files rare reach the 4079 threshold needed to make the shm file
grow.


c2: WAL-mode File Format
c3: 2.1. The WAL-Index Header
c5: walformat.html#the_wal_index_header
c4:
The first 136 bytes of the shm file are a header.  The shm header has
three main divisions as follows:


WAL-Index Header Divisions

BytesDescription
0..47First copy of the WAL Index Information
48..95Second copy of the WAL Index Information
96..135Checkpoint Information and Locks



Individual fields of the shm header, except for the
salt values copied from the WAL header, are unsigned integers
in the native byte-order of the host machine.  The salt values
are exact copies from the WAL header and are in whatever byte
order is used by the WAL file.
The size of integers may be 8, 16, 32, or 64 bits.
A detailed breakout of the individual fields of the shm header
follows:


WAL-Index Header Details

BytesNameMeaning

0..3iVersion
The WAL-index format version number.  Always 3007000.


4..7&nbsp;
Unused padding space.  Must be zero.


8..11iChange
Unsigned integer counter, incremented with each transaction


12isInit
The "isInit" flag.  1 when the shm file has been initialized.


13bigEndCksum
True if the WAL file uses big-ending checksums.  0 if the WAL
    uses little-endian checksums.


14..15szPage
The database page size in bytes, or 1 if the page size is 65536.


16..19mxFrame
Number of valid and committed frames in the WAL file.


20..23nPage
Size of the database file in pages.


24..31aFrameCksum
Checksum of the last frame in the WAL file.


32..39aSalt
The two salt value copied from the WAL file header.
These values are in the byte-order of the WAL file, which
might be different from the native byte-order of the
machine.


40..47aCksum
A checksum over bytes 0 through 39 of this header.


48..95&nbsp;
A copy of bytes 0 through 47 of this header.


96..99nBackfill
Number of WAL frames that have already been backfilled into the database
    by prior checkpoints


100..119read-mark&#91;0..4&#93;
Five "read marks".  Each read mark is a 32-bit unsigned integer (4 bytes).


120..127&nbsp;
Unused space set aside for 8 file locks.


128..132nBackfillAttempted
Number of WAL frames that have attempted to be backfilled but which might
    not have been backfilled successfully.


132..136&nbsp;
Unused space reserved for further expansion.


c2: WAL-mode File Format
c3: 2.1.1. The mxFrame field
c5: walformat.html#the_mxframe_field
c4:
The 32-bit unsigned integer at offset 16 (and repeated at offset 64)
is the number of valid frames in the WAL.  Because WAL frame are numbered
starting with 1, mxFrame is also the index of the last valid commit frame
in the WAL. A commit frame is a frame that has a non-zero "size of database"
value in bytes 4 through 7 of the frame header, and that indicates the end
of a transaction.

When mxFrame field is zero, it indicates that the WAL is empty and that
all content should be obtained directly from the database file.

When mxFrame is equal to nBackfill, that indicates that all content
in the WAL has been written back into the database.
In that case, all content can be read directly from the database.
Furthermore, the next writer is free to reset the WAL if no other
connections hold locks on WAL_READ_LOCK(N) for N>0.

The mxFrame value is always greater than or equal to both
nBackfill and nBackfillAttempted.


c2: WAL-mode File Format
c3: 2.1.2. The nBackfill field
c5: walformat.html#the_nbackfill_field
c4:
The 32-bit unsigned integer at offset 128 in the WAL-index header
is called the "nBackfill".
this field holds the number of frames in the WAL file which
have been copied back into the main database.

The nBackfill number is never greater than mxFrame.
When nBackfill equals mxFrame, that means that the WAL content
has been completely written back into the database and it is
ok to reset the WAL if there are no locks held on any of WAL_READ_LOCK(N)
for N>0.

The nBackfill can only be increased while holding the
WAL_CKPT_LOCK.  However, nBackfill is changed to zero
during a WAL reset, and this happens while holding
the WAL_WRITE_LOCK.


c2: WAL-mode File Format
c3: 2.1.3. WAL Locks
c5: walformat.html#wal_locks
c4:
Eight bytes of space are set aside in the header to support
file locking using the xShmLock() method in the sqlite3_io_methods
object.  These eight bytes are never read nor written by SQLite since
some VFSes (ex: Windows) might implement locks using mandatory file locks.

These are the eight locks supported:


WAL-Index Locks Controlled By xShmLock()

NameOffset
xShmLockFile

WAL_WRITE_LOCK
0
120



WAL_CKPT_LOCK
1
121



WAL_RECOVER_LOCK
2
122



WAL_READ_LOCK(0)
3
123



WAL_READ_LOCK(1)
4
124



WAL_READ_LOCK(2)
5
125



WAL_READ_LOCK(3)
6
126



WAL_READ_LOCK(4)
7
127






TBD:  More information about the header


c2: WAL-mode File Format
c3: 2.2. WAL-Index Hash Tables
c5: walformat.html#wal_index_hash_tables
c4:
The hash tables in the shm file are designed to answer the
following question quickly:


FindFrame(P,M):
Given a page number P and a maximum WAL frame index M,
return the largest WAL frame index for page P that does not exceed M, 
or return NULL if there are no frames for page P that do not exceed M.



Let the datatypes "u8", "u16", and "u32" mean unsigned integers of
length 8, 16, and 32 bits, respectively.  Then, the first 32768-byte unit
of the shm file is organized as follows:


u8 aWalIndexHeader[136];
u32 aPgno[4062];
u16 aHash[8192];


The second and all subsequent 32768-byte units of the shm file are
like this:


u32 aPgno[4096];
u16 aHash[8192];


Collectively, the aPgno entries record the database page number stored
in all frames of the WAL file.  The aPgno[0] entry on the first hash table
records the database page number stored in the very first frame in the WAL 
file. The aPgno[i] entry from the first hash table is the database page number
for the i-th frame in the WAL file.  The aPgno[k] entry for the second
hash table is the database page number for the (k+4062)-th frame in the
WAL file.  The aPgno[k] entry for the n-th 32768-byte hash table in the
shm file (for n>1) holds the database page number stored in the
(k+4062+4096*(n-2))-th frame of the WAL file.

Here is a slightly different way to describe the aPgno values:
If you think of all aPgno values as a contiguous array, then
the database page number stored in the i-th frame of the WAL file
is stored in aPgno[i].  Of course, aPgno is not a contiguous array.
The first 4062 entries are on the first 32768-byte unit of the shm
file and subsequent values are in 4096 entry chunks in later units
of the shm file.

One way to compute FindFrame(P,M) would be to scan the aPgno
array starting with the M-th entry and working backwards towards
the beginning and return J where aPgno[J]==P.  Such an algorithm would
work, and it would be faster than searching the whole WAL file for
the latest frame with page number P.  But the search can be made
much faster still by using the aHash structure.

A database page number P is mapped into a hash value
using the following hash function:


h = (P * 383)%8192


This function maps every page number into an integer between 0
and 8191 inclusive.  The aHash field of each 32768-byte shm file unit
maps P values into indexes of the aPgno field of the same unit as
follows:


 Compute the hash value: h = P * 383
 Let X be the largest set of consecutive integers {h, h+1, h+2, ..., h+N}
     such that for every j in X, aPgno&#91;j%8192]!=0.  The X set will be empty
     if aPgno&#91;h%8192]==0.  The X set is easily computed by starting with
     the value h%8192, and adding h%8192 to X and incrementing h until
     encountering the first aPgno&#91;h%8192] entry that is zero.
 The set X contains the index in aPgno of every entry in the current
     32768-byte unit of the shm file that might possible be a solution
     to the FindFrame(P,M) function.  Each of these entries must be
     checked separately to ensure that the aPgno value is P and that the
     frame number does not exceed M.  The largest frame number that passes
     those two tests is the answer.


Each entry in the aPgno array has a single corresponding entry
in the aHash array.  There are more available slots in aHash than
there are in aPgno.  The unused slots in aHash are filled with zero.
And since there are guaranteed to be unused slots in aHash, that means
the loop that computes X is guaranteed to terminate.  The expected size
of X is less than 2.  The worst case is that X will be the same as the
number of entries in aPgno, in which case the algorithm runs at about
the same speed as a linear scan of aPgno.  But that worst case performance
is exceedingly rare.  Usually, the size of X will be small and the use
of the aHash array allows one to compute FindFrame(P,M) much faster.

Here is an alternative way of describing the hash look-up algorithm:
Start with h = (P * 383)%8192 and look at aHash[h] and subsequent entries,
wrapping around to zero when h reaches 8192, until finding an entry with
aHash[h]==0.  All aPgno entries having a page number of P will have an
index that is one of the aHash[h] values thusly computed.
But not all the computed aHash[h] values will
meet the matching criteria, so you must check them independently.  The
speed advantage comes about because normally this set of h values is
very small.

Note that each 32768-byte unit of the shm file has its own aHash and
aPgno arrays.  The aHash array for a single unit is only helpful in finding
aPgno entries in that same unit.  The overall FindFrame(P,M) function
needs to do hash lookups beginning with the latest unit and working
backwards to the oldest unit until it finds an answer.


c2: WAL-mode File Format
c3: 2.3. Locking Matrix
c5: walformat.html#locking_matrix
c4:
Access is coordinated in WAL mode using both the legacy DELETE-mode
locks controlled by the xLock and xUnlock methods of the sqlite3_io_methods
object and the WAL locks controlled by the xShmLock method of the
sqlite3_io_methods object.

Conceptually, there is just a single DELETE-mode lock.  The DELETE-mode
lock for a single database connection can be in exactly one of the
following states:

 SQLITE_LOCK_NONE (unlocked)
 SQLITE_LOCK_SHARED (reading)
 SQLITE_LOCK_RESERVED (reading, waiting to write)
 SQLITE_LOCK_PENDING (new readers blocked, waiting to write)
 SQLITE_LOCK_EXCLUSIVE (writing)

The DELETE-mode locks are stored on the lock-byte page of the
main database file.
Only SQLITE_LOCK_SHARED and SQLITE_LOCK_EXCLUSIVE are factors for WAL-mode
databases.
The other locking states are used in rollback-mode, but not in WAL-mode.

The WAL-mode locks are described above.


c2: WAL-mode File Format
c3: 2.3.1. How the various locks are used
c5: walformat.html#how_the_various_locks_are_used
c4:
The following rules show how each of the locks is used.


SQLITE_LOCK_SHARED

All connections hold SQLITE_LOCK_SHARED continuously while attached
to a WAL-mode database.  This is true for both read/write connections
and read-only connections.
The SQLITE_LOCK_SHARED lock is held even by connections that are
not within transaction.
This is different from rollback mode, where the SQLITE_LOCK_SHARED is
released at the end of each transaction.

SQLITE_LOCK_EXCLUSIVE

Connections hold an exclusive lock when change in between WAL mode
and any of the various rollback-modes.  Connections might also attempt to
obtain an EXCLUSIVE lock when they disconnect from WAL mode.  If
a connection is able to obtain an EXCLUSIVE lock, that means it is the
only connection to the database and so it may attempt to checkpoint
and then delete the WAL-index and WAL files.

When a connection is holding a SHARED lock on the main database,
that will prevent any other connection from acquiring the EXCLUSIVE
lock, which in turn prevents the WAL-index and WAL files from being
deleted out from under other users, and prevents a transition out of
WAL-mode while other users are accessing the database in WAL-mode.


WAL_WRITE_LOCK

The WAL_WRITE_LOCK is only locked exclusively.  There is never a shared
lock taken on WAL_WRITE_LOCK.

An EXCLUSIVE WAL_WRITE_LOCK is held by any connection that is appending
content to the end of the WAL.  Hence, only a single process at a time
can append content to the WAL.  If a WAL reset occurs as a consequence of
a write, then the nBackfill field of the WAL-index header is reset to
zero while holding this lock.
An EXCLUSIVE is also held WAL_WRITE_LOCK, and on several other locking
bytes, when a connection is running recovery on the shared WAL-index.

WAL_CKPT_LOCK

The WAL_CKPT_LOCK is only locked exclusively.  There is never a shared
lock taken on WAL_CKPT_LOCK.

An EXCLUSIVE WAL_CKPT_LOCK is held by any connection that is running
a checkpoint.  The nBackfill field of the WAL-index header may be
increased while holding this exclusive lock, but it may not be decreased.
An EXCLUSIVE is also held WAL_CKPT_LOCK, and on several other locking
bytes, when a connection is running recovery on the shared WAL-index.

WAL_RECOVER_LOCK

The WAL_RECOVER_LOCK is only locked exclusively.  There is never a shared
lock taken on WAL_RECOVER_LOCK.

An EXCLUSIVE WAL_RECOVER_LOCK is held by any connection that is running
recovery to reconstruct the shared WAL-index.

A read-only connection that is rebuilding its private heap-memory WAL-index
does not hold this lock.  (It cannot, since read-only connections are not
allowed to hold any exclusive locks.)  This lock is only held when rebuilding
the global shared WAL-index contained in the memory-mapped SHM file.

In addition to locking this byte, a connection running recovery also
gets an exclusive lock on all other WAL locks except for WAL_READ_LOCK(0).

WAL_READ_LOCK(N)

There are five separate read locks, numbers 0 through 4.
Read locks may be either SHARED or EXCLUSIVE.
Connections obtain a shared lock on one of the read locks bytes while
they are within a transaction.
Connections also obtain an exclusive lock on read locks, one at a time,
for the brief moment while they are updating the values of the corresponding
read-marks.
Read locks 1 through 4 are held exclusively when running recovery.

Each read lock byte corresponds to one of the five 32-bit read-mark
integers located in bytes 100 through 119 of the WAL-index header, as
follows:


Lock NameLock offsetRead-mark nameRead-mark offset
WAL_READ_LOCK(0)123read-mark[0]100..103
WAL_READ_LOCK(1)124read-mark[1]104..107
WAL_READ_LOCK(2)125read-mark[2]108..111
WAL_READ_LOCK(3)126read-mark[3]112..115
WAL_READ_LOCK(4)127read-mark[4]116..119



When a connection holds a shared lock on WAL_READ_LOCK(N), that is a
promise by the connection that it will use the WAL and not the database
file for any database pages that are modified by the first
read-mark[N] entries in the WAL.
The read-mark[0] is always zero.  If a connection holds a shared lock
on WAL_READ_LOCK(0), that means the connection expects to be able to ignore
the WAL and read any content it wants from the main database.
If N>0 then the connection is free to use more of the WAL file beyond
read-mark[N] if it wants to, up to the first mxFrame frames.
But when a connection holds a shared lock on WAL_READ_LOCK(0), that is a
promise that it will never read content from the WAL
and will acquire all content directly from the main database.

When a checkpoint runs, if it sees a lock on WAL_READ_LOCK(N), then it
must not move WAL content into the main database for more than the first
read-mark[N] frames.  Were it to do so, it would overwrite content that
the process holding the lock was expecting to be able to read out of the
main database file.  A consequence of if this is that f the WAL file
contains more than read-mark[N] frames (if mxFrame>read-mark[N]
for any read-mark for which WAL_READ_LOCK(N) is held by another process),
then the checkpoint cannot run to completion.

When a writer wants to reset the WAL, it must ensure that there are
no locks on WAL_READ_LOCK(N) for N>0 because such locks indicate
that some other connection is still using the current WAL file and 
a WAL reset would delete content out from those other connections.  It is
ok for a WAL reset to occur if other connections are holding WAL_READ_LOCK(0)
because by holding WAL_READ_LOCK(0), those other connections are promising
not to use any content from the WAL.


c2: WAL-mode File Format
c3: 2.3.2. Operations that require locks and which locks those operations use
c5: walformat.html#operations_that_require_locks_and_which_locks_those_operations_use
c4:
Transition into and out of WAL-mode

The SQLITE_LOCK_EXCLUSIVE lock must be held by a connection that wants
to transition into our out of WAL mode.
Transitioning into WAL mode is, therefore, just like any other write
transaction, since every write transaction in rollback mode requires
the SQLITE_LOCK_EXCLUSIVE lock.
If the database file is already in WAL mode (hence if the desire it to change
it back into rollback mode) and if there are two
or more connections to the database, then each of these connections will
be holding an SQLITE_LOCK_SHARED lock.  That means that the
SQLITE_LOCK_EXCLUSIVE cannot be obtained, and the transition out of
WAL mode will not be allowed.  This prevents one connection from deleting
WAL mode out from under another.  It also means that the only way to move
a database from WAL mode into rollback mode is to close all but one
connection to the database.


Close a connection to a WAL mode database

When a database connection closes (via sqlite3_close() or
sqlite3_close_v2()), an attempt is made to acquire
SQLITE_LOCK_EXCLUSIVE.  If this attempt is successful, that means
the connection that is closing is the last connection to the database.
In that case, it is desirable to clean up the WAL and WAL-index files,
so the closing connection runs a checkpoint (while holding
SQLITE_LOCK_EXCLUSIVE) and the deletes both the WAL and WAL-index files.
The SQLITE_LOCK_EXCLUSIVE is not released until after both the
WAL and WAL-index files have been deleted.

If the application invokes
sqlite3_file_control(SQLITE_FCNTL_PERSIST_WAL) on the database
connection prior to closing, then the final checkpoint is still
run but the WAL and WAL-index files are
not deleted as they normally would be.
This leaves the database in a state that allows other processes
without write permission on the database, WAL, or WAL-index files
to open the database read-only.
If the WAL and WAL-index files are missing, then a process that
lacks permission to create and initialize those files will not be
able to open the database, unless the database is designated
as immutable using the immutable query parameter.

Reconstruct the global shared WAL-index during recovery

All of the WAL-index locks, except for WAL_READ_LOCK(0),
are held exclusively while reconstructing the global shared WAL-index
during recovery.  

Append a new transaction to the end of the WAL

An exclusive lock is held on WAL_WRITE_LOCK while adding new
frame onto the end of a WAL file.  

Read content from the database and WAL as part of a transaction

Run a checkpoint

Reset the WAL file

A WAL reset means to rewind the WAL and start adding new frames
at the beginning.  This occurs while appending new frames to a WAL
that has mxFrame equal to nBackfill and which has no locks on
WAL_READ_LOCK(1) through WAL_READ_LOCK(4).  The WAL_WRITE_LOCK is
held.


c2: WAL-mode File Format
c3: 3. Recovery
c5: walformat.html#recovery
c4:
Recovery is the process of rebuilding the WAL-index so that it is
synchronized with the WAL.


Recovery is run by the first thread to connect to a WAL-mode database.
Recovery restores the WAL-index so that it accurately describes the
WAL file.  If there is no WAL file present when the first thread connects
to the database, there is nothing to recover, but the recovery process
still runs to initialize the WAL-index.


If the WAL-index is implemented as a memory-mapped file and that file is
read-only to the first thread to connect, then that thread creates an
private heap-memory ersazt WAL-index and runs the recovery routine to
populate that private WAL-index.  The same data results, but it is held
privately rather that being written into the public shared memory area.


Recovery works by doing a single pass over the WAL, from beginning to end.
The checksums are verified on each frame of the WAL as it is read.  The
scan stops at the end of the file or at the first invalid checksum.
The mxFrame field is set to the index of the last valid commit frame
in WAL.  Since WAL frame numbers are indexed starting with 1, mxFrame is
also the number of valid frames in the WAL.  A "commit frame" is a frame
that has a non-zero value in bytes 4 through 7 of the frame header.
Since the recovery procedure has no way of knowing how many frames of the
WAL might have previously been copied back into the database, it initializes
the nBackfill value to zero.


During recovery of the global shared-memory WAL-index, exclusive locks are
held on WAL_WRITE_LOCK, WAL_CKPT_LOCK, WAL_RECOVER_LOCK, and WAL_READ_LOCK(1) through WAL_READ_LOCK(4).  In other words, all locks associated with the
WAL-index except for WAL_READ_LOCK(0) are held exclusively.  This prevents
any other thread from writing the database and from reading any transactions
that are held in the WAL, until the recovery is complete.
This page last modified on  2019-04-17 15:17:39 UTC


c2: Generated Columns
c3: 1. Introduction
c5: gencol.html#introduction
c4:
Generated columns (also sometimes called "computed columns")
are columns of a table whose values are a function of other columns
in the same row.
Generated columns can be read, but their values can not be directly
written.  The only way to change the value of a generated column is to
modify the values of the other columns used to calculate
the generated column.


c2: Generated Columns
c3: 2. Syntax
c5: gencol.html#syntax
c4:
Syntactically, generated columns are designated using a
"GENERATED ALWAYS" column-constraint.  For example:

CREATE TABLE t1(
   a INTEGER PRIMARY KEY,
   b INT,
   c TEXT,
   d INT GENERATED ALWAYS AS (a*abs(b)) VIRTUAL,
   e TEXT GENERATED ALWAYS AS (substr(c,b,b+1)) STORED
);


The statement above has three ordinary columns, "a" (the PRIMARY KEY),
"b", and "c", and two generated columns "d" and "e".

The "GENERATED ALWAYS" keywords at the beginning of the constraint
and the "VIRTUAL" or "STORED" keyword at the end are all optional.
Only the "AS" keyword and the parenthesized expression are required.
If the trailing "VIRTUAL" or "STORED" keyword is omitted, then
VIRTUAL is the default.  Hence, the example statement above could
be simplified to just:

CREATE TABLE t1(
   a INTEGER PRIMARY KEY,
   b INT,
   c TEXT,
   d INT AS (a*abs(b)),
   e TEXT AS (substr(c,b,b+1)) STORED
);


c2: Generated Columns
c3: 2.1. VIRTUAL versus STORED columns
c5: gencol.html#virtual_versus_stored_columns
c4:
Generated columns can be either VIRTUAL or STORED.  The value of
a VIRTUAL column is computed when read, whereas the value of a STORED
column is computed when the row is written.  STORED columns take up space
in the database file, whereas VIRTUAL columns use more CPU cycles when
being read.

From the point of view of SQL, STORED and VIRTUAL columns are almost
exactly the same.  Queries against either class of generated column
produce the same results.  The only functional difference is that
one cannot add new STORED columns using the
ALTER TABLE ADD COLUMN command.  Only VIRTUAL columns can be added
using ALTER TABLE.


c2: Generated Columns
c3: 2.2. Capabilities
c5: gencol.html#capabilities
c4:
Generated columns can have a datatype.  SQLite attempts to transform
the result of the generating expression into that datatype using the
same affinity rules as for ordinary columns.


Generated columns may have NOT NULL, CHECK, and UNIQUE constraints,
and foreign key constraints, just like ordinary columns.


Generated columns can participate in indexes, just like ordinary
columns.


The expression of a generated column can refer to any of the
other declared columns in the table, including other generated columns,
as long as the expression does not directly or indirectly refer back
to itself.


Generated columns can occur anywhere in the table definition.  Generated
columns can be interspersed among ordinary columns.  It is not necessary
to put generated columns at the end of the list of columns in the
table definition, as is shown in the examples above.


c2: Generated Columns
c3: 2.3. Limitations
c5: gencol.html#limitations
c4:
Generated columns may not have a default value (they may not use the
"DEFAULT" clause).  The value of a generated column is always the value
specified by the expression that follows the "AS" keyword.


Generated columns may not be used as part of the PRIMARY KEY.
(Future versions of SQLite might relax this constraint for STORED columns.)


The expression of a generated column may only reference
constant literals and columns within the same row, and may only use
scalar deterministic functions.  The expression may not use subqueries,
aggregate functions, window functions, or table-valued functions.


The expression of a generated column may refer to other generated columns
in the same row, but no generated column can depend upon itself, either
directly or indirectly.  

The expression of a generated column may not directly reference
the ROWID, though it can reference the INTEGER PRIMARY KEY column,
which is often the same thing.


Every table must have at least one non-generated column.


It is not possible to ALTER TABLE ADD COLUMN a STORED column.
One can add a VIRTUAL column, however.


The datatype and collating sequence of the generated column are determined
only by the datatype and COLLATE clause on the column definition.
The datatype and collating sequence of the GENERATED ALWAYS AS expression
have no affect on the datatype and collating sequence of the column itself.


Generated columns are not included in the list of columns provided by
the PRAGMA table_info statement.  But they are included in the output of
the newer PRAGMA table_xinfo statement.


c2: Generated Columns
c3: 3. Compatibility
c5: gencol.html#compatibility
c4:
Generated column support was added with SQLite version 3.31.0
(2020-01-22).  If an earlier version of SQLite attempts to read
a database file that contains a generated column in its schema, then
that earlier version will perceive the generated column syntax as an
error and will report that the database schema is corrupt.

To clarify:  SQLite version 3.31.0 can read and write any database
created by any prior version of SQLite going back to 
SQLite 3.0.0 (2004-06-18).  And, earlier versions of SQLite,
prior to 3.31.0, can read and write databases created by SQLite
version 3.31.0 and later as long
as the database schema does not contain features, such as
generated columns, that are not understood by the earlier version.
Problems only arise if you create a new database that contains
generated columns, using SQLite version 3.31.0 or later, and then
try to read or write that database file using an earlier version of
SQLite that does not understand generated columns.
This page last modified on  2022-11-09 20:09:19 UTC


c2: The SQLite Zipfile Module
c3: 1. Overview
c5: zipfile.html#overview
c4:
The zipfile module provides read/write access to simple 
ZIP archives.
The current implementation has the following restrictions:


   Does not support encryption.
   Does not support ZIP archives that span multiple files.
   Does not support zip64 extensions.
   The only compression algorithm supported is
       "deflate".


 Some or all of these restrictions may be removed in the future.


c2: The SQLite Zipfile Module
c3: 2. Obtaining and Compiling Zipfile
c5: zipfile.html#obtaining_and_compiling_zipfile
c4:
The code for the zipfile module is found in the 
ext/misc/zipfile.c
file of the
main SQLite source tree.
It may be compiled into an SQLite 
loadable extension using a command like:

gcc -g -fPIC -shared zipfile.c -o zipfile.so


Alternatively, the zipfile.c file may be compiled into the application. 
In this case, the following function should be invoked to register the
extension with each new database connection:

int sqlite3_zipfile_init(sqlite3 *db, void*, void*);


 The first argument passed should be the database handle to register the
extension with. The second and third arguments should both be passed 0.

 Zipfile is included in most builds of the command-line shell.


c2: The SQLite Zipfile Module
c3: 3. Using Zipfile
c5: zipfile.html#using_zipfile
c4:
The zipfile module provides three similar interfaces for accessing, updating
and creating zip file archives:


   A table-valued function, which provides read-only access to existing
       archives, either from the file-system or in-memory.
   A virtual table, which provides read and write access to archives
       stored in the file-system.
   An SQL aggregate function, which can be used to create new archives
       in memory.


The zipfile module provides two similar interfaces for accessing zip
archives. A table-valued function, which provides read-only access to
existing archives, and a virtual table interface, which provides both
read and write access.


c2: The SQLite Zipfile Module
c3: 3.1. Table-Valued Function (read-only access)
c5: zipfile.html#table_valued_function_read_only_access_
c4:
For reading existing zip archives, the Zipfile module provides a
table-valued function that accepts a single argument. If the argument
is a text value, then it is a path to a zip archive to read from the
file-system. Or, if the argument is an SQL blob, then it is the zip
archive data itself.

For example, to inspect the contents of zip archive "test.zip" from 
the current directory:

SELECT * FROM zipfile('test.zip');


Or, from the SQLite shell tool (the readfile() 
function reads the contents of a file from the file-system and returns it as a
blob):

SELECT * FROM zipfile( readfile('test.zip') );


The table-valued function returns one row for each record (file, 
directory or symbolic link) in the zip archive. Each row has the 
following columns:


Column&nbsp;NameContents
name  File name/path for the zip file record.
mode  UNIX mode, as returned by stat(2) for the zip file record (an
                  integer). This identifies the type of record (file, directory
                  or symbolic link), and the associated user/group/all 
                  permissions.
mtime  UTC timestamp, in seconds since the UNIX epoch (an integer).
sz     Size of associated data in bytes after it has been 
                   uncompressed (an integer).
rawdata  Raw (possibly compressed) data associated with zip file
                     entry (a blob).
data  If the compression method for the record is either 0 or 8
                  (see below), then the uncompressed data associated with the
                  zip file entry. Or, if the compression method is not 0 or 8, 
                  this column contains a NULL value.
method  The compression method used to compress the data (an
                    integer). The value 0 indicates that the data is stored
                    in the zip archive without compression. 8 means the
                    raw deflate algorithm.


c2: The SQLite Zipfile Module
c3: 3.2. Virtual Table Interface (read/write access)
c5: zipfile.html#virtual_table_interface_read_write_access_
c4:
In order to create or modify an existing zip file, a "zipfile" virtual 
table must be created in the database schema. The CREATE VIRTUAL TABLE
statement expects a path to the zip file as its only argument. For example, to
write to zip file "test.zip" in the current directory, a zipfile table may be
created using:

CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip');


Such a virtual table has the same columns as the table-valued function
described in the previous section. It may be read from using a SELECT 
statement in the same way as the table-valued function can. 

Using the virtual table interface, new entries may be added to a zip
archive by inserting new rows into the virtual table. Entries may be
removed by deleting rows or modified by updating them.


c2: The SQLite Zipfile Module
c3: 3.2.1. Adding Entries to a Zip Archive
c5: zipfile.html#adding_entries_to_a_zip_archive
c4:
Entries may be added to a zip archive by inserting new rows. The easiest
way to do this is to specify values for the "name" and "data" columns only and
have zipfile fill in sensible defaults for other fields.  To insert a directory
into the archive, set the "data" column to NULL.  For example, to add the
directory "dir1" and the file "m.txt" containing the text "abcdefghi" to zip
archive "test.zip":

INSERT INTO temp.zip(name, data) VALUES('dir1', NULL);           -- Add directory 
INSERT INTO temp.zip(name, data) VALUES('m.txt', 'abcdefghi');   -- Add regular file 


When a directory is inserted, if the "name" value does not end with
a '/' character, the zipfile module appends one. This is necessary for
compatibility with other programs (most notably "info-zip") that 
manipulate zip archives.

To insert a symbolic link, the user must also supply a "mode" value.
For example, to add a symbolic link from "link.txt" to "m.txt":

INSERT INTO temp.zip(name, mode, data) VALUES('link.txt', 'lrwxrw-rw-', 'abcdefghi');


The following rules and caveats apply to the values specified as part of
each INSERT statement:


Columns  Notes
 name
   A non-NULL text value must be specified for the name column. 
       It is an error if the specified name already exists in the
       archive. 

 mode
   If NULL is inserted into the mode column, then the mode of the
       new archive entry is automatically set to either 33188 (-rw-r--r--)
       or 16877 (drwxr-xr-x), depending on whether or not the values 
       specified for columns "sz", "data" and "rawdata" indicate that
       the new entry is a directory.
       
       If the specified value is an integer (or text that looks like
       an integer), it is inserted verbatim. If the value is not a valid UNIX
       mode, some programs may behave unexpectedly when extracting files
       from the archive.

       Finally, if the value specified for this column is not an integer
       or a NULL, then it is assumed to be a UNIX permissions string similar
       to those output by the "ls -l" command (e.g. "-rw-r--r--", "drwxr-xr-x"
       etc.). In this case, if the string cannot be parsed it is an error.

 mtime
   If NULL is inserted into the mtime column, then the timestamp
       of the new entry is set to the current time. Otherwise, the specified
       value is interpreted as an integer and used as is.

 sz
   This column must be set to NULL. If a non-NULL value is inserted into
       this column, or if a new non-NULL value is provided using an UPDATE
       statement, it is an error.

 rawdata
   This column must be set to NULL. If a non-NULL value is inserted into
       this column, or if a new non-NULL value is provided using an UPDATE
       statement, it is an error.

 data

       To insert a directory into the archive, this field must be set to 
       NULL. In this case if a value was explicitly specified for the "mode"
       column, then it must be consistent with a directory (i.e. it must be
       true that (mode & 0040000)=0040000). 

       Otherwise, the value inserted into this field is the file contents
       for a regular file, or the target of a symbolic link.
 method

       This field must be set one of integer values 0 and 8, or else to
       NULL. 

       For a directory entry, any value inserted into this field is ignored.
       Otherwise, if it is set to 0, then the file data or symbolic link
       target is stored as is in the zip archive and the compression method
       set to 0. If it is set to 8, then the file data or link target is
       compressed using deflate compression before it is stored and the
       compression method set to 8. Finally, if a NULL value is written
       to this field, the zipfile module automatically decides whether
       or not to compress the data before storing it.


 Specifying an explicit value for the rowid field as part of an INSERT
statement is not supported. Any value supplied is ignored.


c2: The SQLite Zipfile Module
c3: 3.2.2. Deleting Zip Archive Entries
c5: zipfile.html#_deleting_zip_archive_entries_
c4:
Records may be removed from an existing zip archive by deleting the
corresponding rows. For example, to remove file "m.txt" from zip archive
"test.zip" using the virtual table created above:

DELETE FROM temp.zip WHERE name = 'm.txt';


Note that deleting records from a zip archive does not reclaim the 
space used within the archive - it merely removes an entry from the
archives "Central Directory Structure", making the entry inaccessible.
One way to work around this inefficiency is to create a new zip 
archive based on the contents of the edited archive. For example, after
editing the archive accessed via virtual table temp.zzz:

-- Create a new, empty, archive: 
CREATE VIRTUAL TABLE temp.newzip USING zipfile('new.zip');

-- Copy the contents of the existing archive into the new archive
INSERT INTO temp.newzip(name, mode, mtime, data, method)
    SELECT name, mode, mtime, data, method FROM temp.zzz;


c2: The SQLite Zipfile Module
c3: 3.2.3. Updating Existing Zip Archive Entries
c5: zipfile.html#_updating_existing_zip_archive_entries_
c4:
Existing zip archive entries may be modified using UPDATE statements.

The three leftmost columns of a zipfile virtual table, "name", "mode" 
and "mtime", may each be set to any value that may be inserted into the same
column (see above). If either "mode" or "mtime" is set to NULL, the final 
value is determined as described for an INSERT of a NULL value - the current
time for "mtime" and either 33188 or 16877 for "mode", depending on whether 
or not the values specified for the next four columns of the zipfile table
indicate that the entry is a directory or a file.

It is an error to attempt to set the sz or rawdata field to any value
other than NULL. 

The data and method columns may also be set as described for an INSERT
above.


c2: The SQLite Zipfile Module
c3: 3.3. The zipfile() Aggregate Function
c5: zipfile.html#_the_zipfile_aggregate_function_
c4:
New zip archives may be constructed entirely within memory using the
zipfile() aggregate function. Each row visited by the aggregate function
adds an entry to the zip archive. The value returned is a blob containing
the entire archive image.

 The zipfile() aggregate function may be called with 2, 4 or 5 
arguments. If it is called with 5 arguments, then the entry added to
the archive is equivalent to inserting the same values into the "name", 
"mode", "mtime", "data" and "method" columns of a zipfile virtual table.

 If zipfile() is invoked with 2 arguments, then the entry added to
the archive is equivalent to that added by inserting the same two values into
the "name" and "data" columns of a zipfile virtual table, with all
other values set to NULL. If invoked with 4 arguments, it is equivalent
to inserting the 4 values into the "name", "mode", "mtime" and "data"
columns. In other words, the following pairs of queries are equivalent:

SELECT zipfile(name, data) ...
SELECT zipfile(name, NULL, NULL, data, NULL) ...

SELECT zipfile(name, mode, mtime, data) ...
SELECT zipfile(name, mode, mtime, data, NULL) ...


 For example, to create an archive containing two text files, "a.txt" and
"b.txt", containing the text "abc" and "123" respectively:

WITH contents(name, data) AS (
  VALUES('a.txt', 'abc') UNION ALL
  VALUES('b.txt', '123')
)
SELECT zipfile(name, data) FROM contents;

This page last modified on  2018-03-10 12:09:19 UTC


c2: Pragma statements supported by SQLite
c5: pragma.html#
c4:
PRAGMA Statements



The PRAGMA statement is an SQL extension specific to SQLite and used to 
modify the operation of the SQLite library or to query the SQLite library for 
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.
Some pragmas take effect during the SQL compilation stage, not the
    execution stage. This means if using the C-language sqlite3_prepare(), 
    sqlite3_step(), sqlite3_finalize() API (or similar in a wrapper 
    interface), the pragma may run during the sqlite3_prepare() call,
    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 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
file control which gives VFS implementations the
opportunity to add new PRAGMA statements or to override the meaning of
built-in PRAGMA statements.



PRAGMA command syntax
pragma-stmt:
hide
 
 

pragma-value:
hide
 
 

signed-number:
show
 
 







A pragma can take either zero or one argument.  The argument is may be either
in parentheses or it may be separated from the pragma name by an equal sign.
The two syntaxes yield identical results.
In many pragmas, the argument is a boolean.  The boolean can be one of:



1 yes true on0 no false off


Keyword arguments can optionally appear in quotes.  
(Example:  'yes' &#91;FALSE&#93;.) Some pragmas
takes a string literal as their argument.  When pragma takes a keyword
argument, it will usually also take a numeric equivalent as well.
For example, "0" and "no" mean the same thing, as does "1" and "yes".
When querying the value of a setting, many pragmas return the number
rather than the keyword.

A pragma may have an optional schema-name
before the pragma name.
The schema-name is the name of an ATTACH-ed database 
or "main" or "temp" for the main and the TEMP databases.  If the optional
schema name is omitted, "main" is assumed.  In some pragmas, the schema
name is meaningless and is simply ignored.  In the documentation below,
pragmas for which the schema name is meaningful are shown with a
"schema." prefix.



PRAGMA functions



PRAGMAs that return results and that have no side-effects can be 
accessed from ordinary SELECT statements as table-valued functions.
For each participating PRAGMA, the corresponding table-valued function
has the same name as the PRAGMA with a 7-character "pragma_" prefix.
The PRAGMA argument and schema, if any, are passed as arguments to the
table-valued function, with the schema as an optional, last argument.

For example, information about the columns in an index can be
read using the index_info pragma as follows:


PRAGMA index_info('idx52');


Or, the same content can be read using:


SELECT * FROM pragma_index_info('idx52');


The advantage of the table-valued function format is that the query
can return just a subset of the PRAGMA columns, can include a WHERE clause,
can use aggregate functions, and the table-valued function can be just
one of several data sources in a join.
For example, to get a list of all indexed columns in a schema, one
could query:


SELECT DISTINCT m.name || '.' || ii.name AS 'indexed-columns'
  FROM sqlite_schema AS m,
       pragma_index_list(m.name) AS il,
       pragma_index_info(il.name) AS ii
 WHERE m.type='table'
 ORDER BY 1;



Additional notes:


Table-valued functions exist only for built-in PRAGMAs, not for PRAGMAs
defined using the SQLITE_FCNTL_PRAGMA file control.

Table-valued functions exist only for PRAGMAs that return results and
that have no side-effects.

This feature could be used to implement
information schema
by first creating a separate schema using

ATTACH ':memory:' AS 'information_schema';

Then creating
VIEWs in that schema that implement the official information schema
tables using table-valued PRAGMA functions.

This feature is experimental and is subject to change.  Further documentation
will become available if and when the table-valued functions for PRAGMAs
feature becomes officially supported.

The table-valued functions for PRAGMA feature was added
in SQLite version 3.16.0 (2017-01-02).  Prior versions of SQLite
cannot use this feature.



List Of PRAGMAs


analysis_limit
application_id
auto_vacuum
automatic_index
busy_timeout
cache_size
cache_spill
case_sensitive_like
cell_size_check
checkpoint_fullfsync
collation_list
compile_options
count_changes&sup1;
data_store_directory&sup1;
data_version
database_list
default_cache_size&sup1;
defer_foreign_keys
empty_result_callbacks&sup1;
encoding
foreign_key_check
foreign_key_list
foreign_keys
freelist_count
full_column_names&sup1;
fullfsync
function_list
hard_heap_limit
ignore_check_constraints
incremental_vacuum
index_info
index_list
index_xinfo
integrity_check
journal_mode
journal_size_limit
legacy_alter_table
legacy_file_format
locking_mode
max_page_count
mmap_size
module_list
optimize
page_count
page_size
parser_trace&sup2;
pragma_list
query_only
quick_check
read_uncommitted
recursive_triggers
reverse_unordered_selects
schema_version&sup3;
secure_delete
short_column_names&sup1;
shrink_memory
soft_heap_limit
stats&sup3;
synchronous
table_info
table_list
table_xinfo
temp_store
temp_store_directory&sup1;
threads
trusted_schema
user_version
vdbe_addoptrace&sup2;
vdbe_debug&sup2;
vdbe_listing&sup2;
vdbe_trace&sup2;
wal_autocheckpoint
wal_checkpoint
writable_schema&sup3;



Notes:

Pragmas whose names are struck through
are deprecated. Do not use them. They exist
for historical compatibility.
These pragmas are only available in builds using non-standard
compile-time options.
These pragmas are used for testing SQLite and are not recommended
for use in application programs.


c2: Pragma statements supported by SQLite
c3: PRAGMA analysis_limit
c5: pragma.html#pragma_analysis_limit
c4:
PRAGMA analysis_limit;
        PRAGMA analysis_limit = N;
   Query or change a limit on the approximate ANALYZE setting.
      This is the approximate number of
      rows examined in each index by the ANALYZE command.
      If the argument N is omitted, then the analysis limit
      is unchanged.
      If the limit is zero, then the analysis limit is disabled and
      the ANALYZE command will examine all rows of each index.
      If N is greater than zero, then the analysis limit is set to N
      and subsequent ANALYZE commands will stop analyzing
      each index after it has examined approximately N rows.
      If N is a negative number or something other than an integer value,
      then the pragma behaves as if the N argument was omitted.
      In all cases, the value returned is the new analysis limit used
      for subsequent ANALYZE commands.
   This pragma can be used to help the ANALYZE command run faster
      on large databases.  The results of analysis are not as good
      when only part of each index is examined, but the results are
      usually good enough.  Setting N to 100 or 1000 allows the
      ANALYZE command to run very quickly, even on multi-gigabyte
      database files.  This pragma is particularly useful in combination
      with PRAGMA optimize.
   This pragma was added in SQLite version 3.32.0 (2020-05-22).
      The current implementation only uses the lower 31 bits of the
      N value - higher order bits are silently ignored.  Future versions
      of SQLite might begin using higher order bits.


c2: Pragma statements supported by SQLite
c3: PRAGMA application_id
c5: pragma.html#pragma_application_id
c4:
PRAGMA schema.application_id;
     PRAGMA schema.application_id = integer ;
  
    The application_id PRAGMA is used to query or set the 32-bit
       signed big-endian "Application ID" integer located at offset
       68 into the database header.  Applications that use SQLite as their
       application file-format should set the Application ID integer to
       a unique integer so that utilities such as 
       file(1) can determine the specific
       file type rather than just reporting "SQLite3 Database".  A list of
       assigned application IDs can be seen by consulting the
       magic.txt file in the SQLite source repository.

   See also the user_version pragma.


c2: Pragma statements supported by SQLite
c3: PRAGMA auto_vacuum
c5: pragma.html#pragma_auto_vacuum
c4:
PRAGMA schema.auto_vacuum;
          PRAGMA schema.auto_vacuum = 
           0 | NONE | 1 | FULL | 2 | INCREMENTAL;

    Query or set the auto-vacuum status in the database.

    The default setting for auto-vacuum is 0 or "none",
    unless the SQLITE_DEFAULT_AUTOVACUUM compile-time option is used.
    The "none" setting means that auto-vacuum is disabled.
    When auto-vacuum is disabled and data is deleted data from a database,
    the database file remains the same size.  Unused database file 
    pages are added to a "freelist" and reused for subsequent inserts.  So
    no database file space is lost.  However, the database file does not
    shrink.  In this mode the VACUUM
    command can be used to rebuild the entire database file and
    thus reclaim unused disk space.

    When the auto-vacuum mode is 1  or "full", the freelist pages are
    moved to the end of the database file and the database file is truncated
    to remove the freelist pages at every transaction commit.
    Note, however, that auto-vacuum only truncates the freelist pages
    from the file.  Auto-vacuum does not defragment the database nor
    repack individual database pages the way that the
    VACUUM command does.  In fact, because
    it moves pages around within the file, auto-vacuum can actually
    make fragmentation worse.

    Auto-vacuuming is only possible if the database stores some
    additional information that allows each database page to be
    traced backwards to its referrer.  Therefore, auto-vacuuming must
    be turned on before any tables are created.  It is not possible
    to enable or disable auto-vacuum after a table has been created.

    When the value of auto-vacuum is 2 or "incremental" then the additional
    information needed to do auto-vacuuming is stored in the database file
    but auto-vacuuming does not occur automatically at each commit as it
    does with auto_vacuum=full.  In incremental mode, the separate
    incremental_vacuum pragma must
    be invoked to cause the auto-vacuum to occur.

    The database connection can be changed between full and incremental
    autovacuum mode at any time.  However, changing from
    "none" to "full" or "incremental" can only occur when the database 
    is new (no tables
    have yet been created) or by running the VACUUM command.  To
    change auto-vacuum modes, first use the auto_vacuum pragma to set
    the new desired mode, then invoke the VACUUM command to 
    reorganize the entire database file.  To change from "full" or
    "incremental" back to "none" always requires running VACUUM even
    on an empty database.
    

    When the auto_vacuum pragma is invoked with no arguments, it
    returns the current auto_vacuum mode.


c2: Pragma statements supported by SQLite
c3: PRAGMA automatic_index
c5: pragma.html#pragma_automatic_index
c4:
PRAGMA automatic_index;
     PRAGMA automatic_index = boolean;

    Query, set, or clear the automatic indexing capability.
    Automatic indexing is enabled by default as of 
    version 3.7.17 (2013-05-20),
    but this might change in future releases of SQLite.


c2: Pragma statements supported by SQLite
c3: PRAGMA busy_timeout
c5: pragma.html#pragma_busy_timeout
c4:
PRAGMA busy_timeout;
         PRAGMA busy_timeout = milliseconds;
    Query or change the setting of the
    busy timeout.
    This pragma is an alternative to the sqlite3_busy_timeout() C-language
    interface which is made available as a pragma for use with language
    bindings that do not provide direct access to sqlite3_busy_timeout().

    Each database connection can only have a single
    busy handler.  This PRAGMA sets the busy handler
    for the process, possibly overwriting any previously set busy handler.


c2: Pragma statements supported by SQLite
c3: PRAGMA cache_size
c5: pragma.html#pragma_cache_size
c4:
PRAGMA schema.cache_size;
       PRAGMA schema.cache_size = pages;
       PRAGMA schema.cache_size = -kibibytes;
    Query or change the suggested maximum number of database disk pages
    that SQLite will hold in memory at once per open database file.  Whether
    or not this suggestion is honored is at the discretion of the
    Application Defined Page Cache.
    The default page cache that is built into SQLite honors the request,
    however alternative application-defined page cache implementations
    may choose to interpret the suggested cache size in different ways
    or to ignore it all together.
    The default suggested cache size is -2000, which means the cache size
    is limited to 2048000 bytes of memory.
    The default suggested cache size can be altered using the
    SQLITE_DEFAULT_CACHE_SIZE compile-time options.
    The TEMP database has a default suggested cache size of 0 pages.

    If the argument N is positive then the suggested cache size is set 
    to N. If the argument N is negative, then the
    number of cache pages is adjusted to be a number of pages that would
    use approximately abs(N*1024) bytes of memory based on the current
    page size.  SQLite remembers the number of pages in the page cache,
    not the amount of memory used.  So if you set the cache size using
    a negative number and subsequently change the page size (using the
    PRAGMA page_size command) then the maximum amount of cache
    memory will go up or down in proportion to the change in page size.

    Backwards compatibility note:
    The behavior of cache_size with a negative N
    was different prior to version 3.7.10 (2012-01-16).  In
    earlier versions, the number of pages in the cache was set
    to the absolute value of N.

    When you change the cache size using the cache_size pragma, the
    change only endures for the current session.  The cache size reverts
    to the default value when the database is closed and reopened.

    The default page cache implemention does not allocate
    the full amount of cache memory all at once.  Cache memory
    is allocated in smaller chunks on an as-needed basis.  The page_cache
    setting is a (suggested) upper bound on the amount of memory that the
    cache can use, not the amount of memory it will use all of the time.
    This is the behavior of the default page cache implementation, but an
    application defined page cache is free
    to behave differently if it wants.


c2: Pragma statements supported by SQLite
c3: PRAGMA cache_spill
c5: pragma.html#pragma_cache_spill
c4:
PRAGMA cache_spill;
         PRAGMA cache_spill=boolean;
         PRAGMA schema.cache_spill=N;

    The cache_spill pragma enables or disables the ability of the pager
    to spill dirty cache pages to the database file in the middle of a 
    transaction.  Cache_spill is enabled by default and most applications
    should leave it that way as cache spilling is usually advantageous.
    However, a cache spill has the side-effect of acquiring an
    EXCLUSIVE lock on the database file.  Hence, some applications that
    have large long-running transactions may want to disable cache spilling
    in order to prevent the application from acquiring an exclusive lock
    on the database until the moment that the transaction COMMITs.
    The "PRAGMA cache_spill=N" form of this pragma sets a minimum
    cache size threshold required for spilling to occur. The number of pages
    in cache must exceed both the cache_spill threshold and the maximum cache
    size set by the PRAGMA cache_size statement in order for spilling to
    occur.
    The "PRAGMA cache_spill=boolean" form of this pragma applies
    across all databases attached to the database connection.  But the
    "PRAGMA cache_spill=N" form of this statement only applies to
    the "main" schema or whatever other schema is specified as part of the
    statement.


c2: Pragma statements supported by SQLite
c3: PRAGMA case_sensitive_like
c5: pragma.html#pragma_case_sensitive_like
c4:
PRAGMA case_sensitive_like = boolean;
    The default behavior of the LIKE operator is to ignore case
    for ASCII characters. Hence, by default 'a' LIKE 'A' is
    true.  The case_sensitive_like pragma installs a new application-defined
    LIKE function that is either case sensitive or insensitive depending
    on the value of the case_sensitive_like pragma.
    When case_sensitive_like is disabled, the default LIKE behavior is
    expressed.  When case_sensitive_like is enabled, case becomes
    significant.  So, for example,
    'a' LIKE 'A' is false but 'a' LIKE 'a' is still true.

    This pragma uses sqlite3_create_function() to overload the
    LIKE and GLOB functions, which may override previous implementations
    of LIKE and GLOB registered by the application.  This pragma
    only changes the behavior of the SQL LIKE operator.  It does not
    change the behavior of the sqlite3_strlike() C-language interface,
    which is always case insensitive.


c2: Pragma statements supported by SQLite
c3: PRAGMA cell_size_check
c5: pragma.html#pragma_cell_size_check
c4:
PRAGMA cell_size_check
       PRAGMA cell_size_check = boolean;
    The cell_size_check pragma enables or disables additional sanity
    checking on database b-tree pages as they are initially read from disk.
    With cell size checking enabled, database corruption is detected earlier
    and is less likely to "spread".  However, there is a small performance
    hit for doing the extra checks and so cell size checking is turned off
    by default.


c2: Pragma statements supported by SQLite
c3: PRAGMA checkpoint_fullfsync
c5: pragma.html#pragma_checkpoint_fullfsync
c4:
PRAGMA checkpoint_fullfsync
       PRAGMA checkpoint_fullfsync = boolean;
    Query or change the fullfsync flag for checkpoint operations.
    If this flag is set, then the F_FULLFSYNC syncing method is used
    during checkpoint operations on systems that support F_FULLFSYNC. 
    The default value of the checkpoint_fullfsync flag
    is off.  Only Mac OS-X supports F_FULLFSYNC.

    If the fullfsync flag is set, then the F_FULLFSYNC syncing
    method is used for all sync operations and the checkpoint_fullfsync
    setting is irrelevant.


c2: Pragma statements supported by SQLite
c3: PRAGMA collation_list
c5: pragma.html#pragma_collation_list
c4:
PRAGMA collation_list;
    Return a list of the collating sequences defined for the current
    database connection.


c2: Pragma statements supported by SQLite
c3: PRAGMA compile_options
c5: pragma.html#pragma_compile_options
c4:
PRAGMA compile_options;
    This pragma returns the names of compile-time options used when
    building SQLite, one option per row.  The "SQLITE_" prefix is omitted
    from the returned option names.  See also the
    sqlite3_compileoption_get() C/C++ interface and the
    sqlite_compileoption_get() SQL functions.


c2: Pragma statements supported by SQLite
c3: PRAGMA count_changes
c5: pragma.html#pragma_count_changes
c4:
PRAGMA count_changes;
       PRAGMA count_changes = boolean;

    Query or change the count-changes flag. Normally, when the
    count-changes flag is not set, INSERT, UPDATE and DELETE statements
    return no data. When count-changes is set, each of these commands 
    returns a single row of data consisting of one integer value - the
    number of rows inserted, modified or deleted by the command. The 
    returned change count does not include any insertions, modifications
    or deletions performed by triggers, any changes made automatically
    by foreign key actions, or updates caused by an upsert.

    Another way to get the row change counts is to use the
    sqlite3_changes() or sqlite3_total_changes() interfaces.
    There is a subtle different, though.  When an INSERT, UPDATE, or
    DELETE is run against a view using an INSTEAD OF trigger,
    the count_changes pragma reports the number of rows in the view
    that fired the trigger, whereas sqlite3_changes() and
    sqlite3_total_changes() do not.

    
    
    This pragma is deprecated and exists
    for backwards compatibility only.  New applications
    should avoid using this pragma.  Older applications should discontinue
    use of this pragma at the earliest opportunity.  This pragma may be omitted
    from the build when SQLite is compiled using SQLITE_OMIT_DEPRECATED.


c2: Pragma statements supported by SQLite
c3: PRAGMA data_store_directory
c5: pragma.html#pragma_data_store_directory
c4:
PRAGMA data_store_directory;
      PRAGMA data_store_directory = 'directory-name';
    Query or change the value of the sqlite3_data_directory global
    variable, which windows operating-system interface backends use to
    determine where to store database files specified using a relative
    pathname.

    Changing the data_store_directory setting is not threadsafe.
    Never change the data_store_directory setting if another thread
    within the application is running any SQLite interface at the same time.
    Doing so results in undefined behavior.  Changing the data_store_directory
    setting writes to the sqlite3_data_directory global
    variable and that global variable is not protected by a mutex.

    This facility is provided for WinRT which does not have an OS
    mechanism for reading or changing the current working directory.
    The use of this pragma in any other context is discouraged and may
    be disallowed in future releases.

    
    
    This pragma is deprecated and exists
    for backwards compatibility only.  New applications
    should avoid using this pragma.  Older applications should discontinue
    use of this pragma at the earliest opportunity.  This pragma may be omitted
    from the build when SQLite is compiled using SQLITE_OMIT_DEPRECATED.


c2: Pragma statements supported by SQLite
c3: PRAGMA data_version
c5: pragma.html#pragma_data_version
c4:
PRAGMA schema.data_version;
    The "PRAGMA data_version" command provides an indication that the
    database file has been modified.
    Interactive programs that hold database content in memory or that
    display database content on-screen can use the PRAGMA data_version
    command to determine if they need to flush and reload their memory
    or update the screen display.

    The integer values returned by two
    invocations of "PRAGMA data_version" from the same connection
    will be different if changes were committed to the database 
    by any other connection in the interim.
    The "PRAGMA data_version" value is unchanged for commits made
    on the same database connection.
    The behavior of "PRAGMA data_version" is the same for all database
    connections, including database connections in separate processes
    and shared cache database connections.

    The "PRAGMA data_version" value is a local property of each
    database connection and so values returned by two concurrent invocations
    of "PRAGMA data_version" on separate database connections are 
    often different even though the underlying database is identical.
    It is only meaningful to compare the "PRAGMA data_version" values
    returned by the same database connection at two different points in
    time.


c2: Pragma statements supported by SQLite
c3: PRAGMA database_list
c5: pragma.html#pragma_database_list
c4:
PRAGMA database_list;
    This pragma works like a query to return one row for each database
    attached to the current database connection.
    The second column is "main" for the main database file, "temp"
    for the database file used to store TEMP objects, or the name of the
    ATTACHed database for other database files.
    The third column is the name of the database file itself, or an empty
    string if the database is not associated with a file.


c2: Pragma statements supported by SQLite
c3: PRAGMA default_cache_size
c5: pragma.html#pragma_default_cache_size
c4:
PRAGMA schema.default_cache_size;
       PRAGMA schema.default_cache_size
            = Number-of-pages;

    This pragma queries or sets the suggested maximum number of pages
    of disk cache that will be allocated per open database file.
    The difference between this pragma and cache_size is that the
    value set here persists across database connections.
    The value of the default cache size is stored in the 4-byte
    big-endian integer located at offset 48 in the header of the
    database file.
    

    
    
    This pragma is deprecated and exists
    for backwards compatibility only.  New applications
    should avoid using this pragma.  Older applications should discontinue
    use of this pragma at the earliest opportunity.  This pragma may be omitted
    from the build when SQLite is compiled using SQLITE_OMIT_DEPRECATED.


c2: Pragma statements supported by SQLite
c3: PRAGMA defer_foreign_keys
c5: pragma.html#pragma_defer_foreign_keys
c4:
PRAGMA defer_foreign_keys
       PRAGMA defer_foreign_keys = boolean;
    When the defer_foreign_keys PRAGMA is on,
    enforcement of all foreign key constraints is delayed until the
    outermost transaction is committed.  The defer_foreign_keys pragma
    defaults to OFF so that foreign key constraints are only deferred if
    they are created as "DEFERRABLE INITIALLY DEFERRED".  The 
    defer_foreign_keys pragma is automatically switched off at each
    COMMIT or ROLLBACK.  Hence, the defer_foreign_keys pragma must be
    separately enabled for each transaction.  This pragma is
    only meaningful if foreign key constraints are enabled, of course.

    The sqlite3_db_status(db,SQLITE_DBSTATUS_DEFERRED_FKS,...)
    C-language interface can be used during a transaction to determine 
    if there are deferred and unresolved foreign key constraints.


c2: Pragma statements supported by SQLite
c3: PRAGMA empty_result_callbacks
c5: pragma.html#pragma_empty_result_callbacks
c4:
PRAGMA empty_result_callbacks;
       PRAGMA empty_result_callbacks = boolean;

    Query or change the empty-result-callbacks flag.

    The empty-result-callbacks flag affects the sqlite3_exec() API only.
    Normally, when the empty-result-callbacks flag is cleared, the
    callback function supplied to the sqlite3_exec() is not invoked
    for commands that return zero rows of data.  When empty-result-callbacks
    is set in this situation, the callback function is invoked exactly once,
    with the third parameter set to 0 (NULL). This is to enable programs  
    that use the sqlite3_exec() API to retrieve column-names even when
    a query returns no data.

    
    
    This pragma is deprecated and exists
    for backwards compatibility only.  New applications
    should avoid using this pragma.  Older applications should discontinue
    use of this pragma at the earliest opportunity.  This pragma may be omitted
    from the build when SQLite is compiled using SQLITE_OMIT_DEPRECATED.


c2: Pragma statements supported by SQLite
c3: PRAGMA encoding
c5: pragma.html#pragma_encoding
c4:
PRAGMA encoding;
       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
    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
    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.

    If no encoding is first set with this pragma,
    then the encoding with which the main database will be created
    defaults to one determined by the
    API used to open the connection.

    Once an encoding has been set for a database, it cannot be changed.

    Databases created by the ATTACH command always use the same encoding
    as the main database.  An attempt to ATTACH a database with a different
    text encoding from the "main" database will fail.


c2: Pragma statements supported by SQLite
c3: PRAGMA foreign_key_check
c5: pragma.html#pragma_foreign_key_check
c4:
PRAGMA schema.foreign_key_check;
        PRAGMA schema.foreign_key_check(table-name);

    The foreign_key_check pragma checks the database, or the table
    called "table-name", for 
    foreign key constraints that are violated.  The foreign_key_check
    pragma returns one row output for each foreign key violation.
    There are four columns in each result row.
    The first column is the name of the table that contains the REFERENCES
    clause.  The second column is the rowid of the row that
    contains the invalid REFERENCES clause, or NULL if the child table is a
    WITHOUT ROWID table.  The third column is the name
    of the table that is referred to. The fourth column is the index of
    the specific foreign key constraint that failed.  The fourth column
    in the output of the foreign_key_check pragma is the same integer as
    the first column in the output of the foreign_key_list pragma.
    When a "table-name" is specified, the only foreign key constraints
    checked are those created by REFERENCES clauses in the
    CREATE TABLE statement for table-name.


c2: Pragma statements supported by SQLite
c3: PRAGMA foreign_key_list
c5: pragma.html#pragma_foreign_key_list
c4:
PRAGMA foreign_key_list(table-name);

    This pragma returns one row for each foreign key constraint
    created by a REFERENCES clause in the CREATE TABLE statement of
    table "table-name".


c2: Pragma statements supported by SQLite
c3: PRAGMA foreign_keys
c5: pragma.html#pragma_foreign_keys
c4:
PRAGMA foreign_keys;
       PRAGMA foreign_keys = boolean;
    Query, set, or clear the enforcement of foreign key constraints.

    This pragma is a no-op within a transaction; foreign key constraint
       enforcement may only be enabled or disabled when there is no pending
       BEGIN or SAVEPOINT.

    Changing the foreign_keys setting affects the execution of
       all statements prepared
       using the database connection, including those prepared before the
       setting was changed. Any existing statements prepared using the legacy 
       sqlite3_prepare() interface may fail with an SQLITE_SCHEMA error
       after the foreign_keys setting is changed.

    As of SQLite version 3.6.19, the default setting for foreign
       key enforcement is OFF.  However, that might change in a future
       release of SQLite.  The default setting for foreign key enforcement
       can be specified at compile-time using the SQLITE_DEFAULT_FOREIGN_KEYS
       preprocessor macro.  To minimize future problems, applications should
       set the foreign key enforcement flag as required by the application
       and not depend on the default setting.


c2: Pragma statements supported by SQLite
c3: PRAGMA full_column_names
c5: pragma.html#pragma_full_column_names
c4:
PRAGMA full_column_names;
       PRAGMA full_column_names = boolean;

    Query or change the full_column_names flag. This flag together 
    with the short_column_names flag determine
    the way SQLite assigns names to result columns of SELECT statements.
    Result columns are named by applying the following rules in order:
    
    If there is an AS clause on the result, then the name of
        the column is the right-hand side of the AS clause.
    If the result is a general expression, not a just the name of
        a source table column,
        then the name of the result is a copy of the expression text.
    If the short_column_names pragma is ON, then the name of the
        result is the name of the source table column without the 
        source table name prefix:  COLUMN.
    If both pragmas short_column_names and full_column_names
        are OFF then case (2) applies.
        
    The name of the result column is a combination of the source table
        and source column name:  TABLE.COLUMN
    

    
    
    This pragma is deprecated and exists
    for backwards compatibility only.  New applications
    should avoid using this pragma.  Older applications should discontinue
    use of this pragma at the earliest opportunity.  This pragma may be omitted
    from the build when SQLite is compiled using SQLITE_OMIT_DEPRECATED.


c2: Pragma statements supported by SQLite
c3: PRAGMA fullfsync
c5: pragma.html#pragma_fullfsync
c4:
PRAGMA fullfsync
       PRAGMA fullfsync = boolean;
    Query or change the fullfsync flag. This flag
    determines whether or not the F_FULLFSYNC syncing method is used
    on systems that support it.  The default value of the fullfsync flag
    is off.  Only Mac OS X supports F_FULLFSYNC.

    See also checkpoint_fullfsync.


c2: Pragma statements supported by SQLite
c3: PRAGMA function_list
c5: pragma.html#pragma_function_list
c4:
PRAGMA function_list;
    This pragma returns a list of SQL functions
    known to the database connection.  Each row of the result
    describes a single calling signature for a single SQL function.
    Some SQL functions will have multiple rows in the result set
    if they can (for example) be invoked with a varying number of
    arguments or can accept text in various encodings.


c2: Pragma statements supported by SQLite
c3: PRAGMA hard_heap_limit
c5: pragma.html#pragma_hard_heap_limit
c4:
PRAGMA hard_heap_limit
          PRAGMA hard_heap_limit=N

    This pragma invokes the sqlite3_hard_heap_limit64() interface with
    the argument N, if N is specified and N is a positive integer that
    is less than the current hard heap limit.
    The hard_heap_limit pragma always returns the same integer
    that would be returned by the sqlite3_hard_heap_limit64(-1) C-language
    function.  That is to say, it always returns the value of the hard
    heap limit that is set after any changes imposed by this PRAGMA.
    

    This pragma can only lower the heap limit, never raise it.
    The C-language interface sqlite3_hard_heap_limit64() must be used
    to raise the heap limit.

    See also the soft_heap_limit pragma.


c2: Pragma statements supported by SQLite
c3: PRAGMA ignore_check_constraints
c5: pragma.html#pragma_ignore_check_constraints
c4:
PRAGMA ignore_check_constraints  = boolean;

    This pragma enables or disables the enforcement of CHECK constraints.
    The default setting is off, meaning that CHECK constraints are
    enforced by default.


c2: Pragma statements supported by SQLite
c3: PRAGMA incremental_vacuum
c5: pragma.html#pragma_incremental_vacuum
c4:
PRAGMA schema.incremental_vacuum(N);
      PRAGMA schema.incremental_vacuum;
    The incremental_vacuum pragma causes up to N pages to
    be removed from the freelist.  The database file is truncated by
    the same amount.  The incremental_vacuum pragma has no effect if
    the database is not in
    auto_vacuum=incremental mode
    or if there are no pages on the freelist.  If there are fewer than
    N pages on the freelist, or if N is less than 1, or
    if the "(N)" argument is omitted, then the entire
    freelist is cleared.


c2: Pragma statements supported by SQLite
c3: PRAGMA index_info
c5: pragma.html#pragma_index_info
c4:
PRAGMA schema.index_info(index-name);
    This pragma returns one row for each key column in the named index.
    A key column is a column that is actually named in the CREATE INDEX
    index statement or UNIQUE constraint or PRIMARY KEY constraint that
    created the index.  Index entries also usually contain auxiliary
    columns that point back to the table row being indexed.  The auxiliary
    index-columns are not shown by the index_info pragma, but they are
    listed by the index_xinfo pragma.

    Output columns from the index_info pragma are as follows:
    
    The rank of the column within the index.  (0 means left-most.)
    The rank of the column within the table being indexed.
        A value of -1 means rowid and a value of -2 means that an
        expression is being used.
    The name of the column being indexed.  This columns is NULL
        if the column is the rowid or an expression.
    

    If there is no index named index-name but there is a
    WITHOUT ROWID table with that name, then (as of
    SQLite version 3.30.0 on 2019-10-04) this pragma returns the
    PRIMARY KEY columns of the WITHOUT ROWID table as they are used
    in the records of the underlying b-tree, which is to say with
    duplicate columns removed.


c2: Pragma statements supported by SQLite
c3: PRAGMA index_list
c5: pragma.html#pragma_index_list
c4:
PRAGMA schema.index_list(table-name);
    This pragma returns one row for each index associated with the
    given table.
    Output columns from the index_list pragma are as follows:
    
    A sequence number assigned to each index for internal tracking
          purposes.
    The name of the index.
    "1" if the index is UNIQUE and "0" if not.
    "c" if the index was created by a CREATE INDEX statement,
          "u" if the index was created by a UNIQUE constraint, or
          "pk" if the index was created by a PRIMARY KEY constraint.
    "1" if the index is a partial index and "0" if not.


c2: Pragma statements supported by SQLite
c3: PRAGMA index_xinfo
c5: pragma.html#pragma_index_xinfo
c4:
PRAGMA schema.index_xinfo(index-name);
    This pragma returns information about every column in an index.
    Unlike this index_info pragma, this pragma returns information about
    every column in the index, not just the key columns.
    (A key column is a column that is actually named in the CREATE INDEX
    index statement or UNIQUE constraint or PRIMARY KEY constraint that
    created the index.  Auxiliary columns are additional columns needed to
    locate the table entry that corresponds to each index entry.)

    Output columns from the index_xinfo pragma are as follows:
    
    The rank of the column within the index. (0 means left-most.
         Key columns come before auxiliary columns.)
    The rank of the column within the table being indexed, or -1 if
         the index-column is the rowid of the table being indexed and -2
         if the index is on an expression.
    The name of the column being indexed, or NULL if the index-column
         is the rowid of the table being indexed or an
         expression.
    1 if the index-column is sorted in reverse (DESC) order by the
         index and 0 otherwise.
    The name for the collating sequence
         used to compare values in the index-column.
    1 if the index-column is a key column and 0 if the index-column
         is an auxiliary column.
    

    If there is no index named index-name but there is a
    WITHOUT ROWID table with that name, then (as of
    SQLite version 3.30.0 on 2019-10-04) this pragma returns the
    columns of the WITHOUT ROWID table as they are used
    in the records of the underlying b-tree, which is to say with
    de-duplicated PRIMARY KEY columns first followed by data columns.


c2: Pragma statements supported by SQLite
c3: PRAGMA integrity_check
c5: pragma.html#pragma_integrity_check
c4:
PRAGMA schema.integrity_check;
      PRAGMA schema.integrity_check(N)
      PRAGMA schema.integrity_check(TABLENAME)
    This pragma does a low-level formatting and consistency check
    of the database.  The integrity_check pragma look for:
    
     Table or index entries that are out of sequence
     Misformatted records
     Missing pages
     Missing or surplus index entries
     UNIQUE, CHECK, and NOT NULL constraint errors
     Integrity of the freelist
     Sections of the database that are used more than once, or not at all
    
    If the integrity_check pragma finds problems, strings are returned
    (as multiple rows with a single column per row) which describe
    the problems.  Pragma integrity_check will return at most N
    errors before the analysis quits, with N defaulting
    to 100.  If pragma integrity_check finds no errors, a
    single row with the value 'ok' is returned.

    The usual case is that the entire database file is checked.  However,
    if the argument is TABLENAME, then checking is only performed for the
    the table named and its associated indexes.
    This is called a "partial integrity check".  Because only a subset of the
    database is checked, errors such as unused sections of the file or duplication
    use of the same section of the file by two or more tables cannot be detected.
    The freelist is only verified on a
    partial integrity check if TABLENAME is sqlite_schema or one of its
    aliases.  Support for partial integrity checks was added with
    version 3.33.0 (2020-08-14).

    PRAGMA integrity_check does not find
    FOREIGN KEY errors.  
    Use the PRAGMA foreign_key_check command to find errors in
    FOREIGN KEY constraints.

    See also the PRAGMA quick_check command which does most of the
    checking of PRAGMA integrity_check but runs much faster.


c2: Pragma statements supported by SQLite
c3: PRAGMA journal_mode
c5: pragma.html#pragma_journal_mode
c4:
PRAGMA schema.journal_mode;
        PRAGMA schema.journal_mode
              = DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF

    This pragma queries or sets the journal mode for databases
    associated with the current database connection.

    The first form of this pragma queries the current journaling
    mode for database.  When database is omitted, the
    "main" database is queried.

    The second form changes the journaling mode for "database"
    or for all attached databases if "database" is omitted.
    The new journal mode is returned.  If the journal mode
    could not be changed, the original journal mode is returned.

    The DELETE journaling mode is the normal behavior.  In the DELETE
    mode, the rollback journal is deleted at the conclusion of each
    transaction.  Indeed, the delete operation is the action that causes
    the transaction to commit.
    (See the document titled 
    Atomic Commit In SQLite for additional detail.)

    The TRUNCATE journaling mode commits transactions by truncating
    the rollback journal to zero-length instead of deleting it.  On many
    systems, truncating a file is much faster than deleting the file since
    the containing directory does not need to be changed.

    The PERSIST journaling mode prevents the rollback journal from
    being deleted at the end of each transaction.  Instead, the header
    of the journal is overwritten with zeros.  This will prevent other
    database connections from rolling the journal back.  The PERSIST
    journaling mode is useful as an optimization on platforms where
    deleting or truncating a file is much more expensive than overwriting
    the first block of a file with zeros.  See also:
    PRAGMA journal_size_limit and SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT.

    The MEMORY journaling mode stores the rollback journal in 
    volatile RAM.  This saves disk I/O but at the expense of database
    safety and integrity.  If the application using SQLite crashes in
    the middle of a transaction when the MEMORY journaling mode is set,
    then the database file will very likely 
    go corrupt.

    The WAL journaling mode uses a write-ahead log instead of a
    rollback journal to implement transactions.  The WAL journaling mode
    is persistent; after being set it stays in effect
    across multiple database connections and after closing and
    reopening the database.  A database in WAL journaling mode
    can only be accessed by SQLite version 3.7.0 (2010-07-21)
    or later.

    The OFF journaling mode disables the rollback journal completely.
    No rollback journal is ever created and hence there is never a rollback
    journal to delete.  The OFF journaling mode disables the atomic
    commit and rollback capabilities of SQLite. The ROLLBACK command
    no longer works; it behaves in an undefined way.  Applications must
    avoid using the ROLLBACK command when the journal mode is OFF.
    If the application crashes
    in the middle of a transaction when the OFF journaling mode is
    set, then the database file will very likely
    go corrupt. Without a journal, there is no way for
    a statement to unwind partially completed operations following
    a constraint error.  This might also leave the database in a corrupted
    state.  For example, if a duplicate entry causes a 
    CREATE UNIQUE INDEX statement to fail half-way through,
    it will leave behind a partially created, and hence corrupt, index.
    Because OFF journaling
    mode allows the database file to be corrupted using ordinary SQL,
    it is disabled when SQLITE_DBCONFIG_DEFENSIVE is enabled.

    Note that the journal_mode for an in-memory database
    is either MEMORY or OFF and can not be changed to a different value.
    An attempt to change the journal_mode of an in-memory database to
    any setting other than MEMORY or OFF is ignored.  Note also that
    the journal_mode cannot be changed while a transaction is active.


