# page_content

c2: JSON Functions And Operators
c5: json1.html
c4:
1. Overview

By default, SQLite supports fifteen functions and two operators for
dealing with JSON values.  There are also two table-valued functions
that can be used to decompose a JSON string.


There are 15 scalar functions and operators:



json(json)



json_array(value1,value2,...)



json_array_length(json)json_array_length(json,path)



json_extract(json,path,...)



json -> path



json ->> path



json_insert(json,path,value,...)



json_object(label1,value1,...)



json_patch(json1,json2)



json_remove(json,path,...)



json_replace(json,path,value,...)



json_set(json,path,value,...)



json_type(json)json_type(json,path)



json_valid(json)



json_quote(value)





There are two aggregate SQL functions:



json_group_array(value)



json_group_object(name,value)





The two table-valued functions are:



json_each(json)json_each(json,path)



json_tree(json)json_tree(json,path)












2. Compiling in JSON Support


The JSON functions and operators are built into SQLite by default,
as of SQLite version 3.38.0 (2022-02-22).  They can be omitted
by adding the -DSQLITE_OMIT_JSON compile-time option.  Prior to
version 3.38.0, the JSON functions were an extension that would only
be included in builds if the -DSQLITE_ENABLE_JSON1 compile-time option
was included.  In other words, the JSON functions went from being
opt-in with SQLite version 3.37.2 and earlier to opt-out with
SQLite version 3.38.0 and later.

3. Interface Overview


SQLite stores JSON as ordinary text.
Backwards compatibility constraints mean that SQLite is only able to
store values that are NULL, integers, floating-point numbers, text,
and BLOBs.  It is not possible to add a sixth "JSON" type.


SQLite does not (currently) support a binary encoding
of JSON.  Experiments have been unable to find a binary encoding
that is significantly smaller or faster than a plain text encoding.
(The present implementation parses JSON text at over 1 GB/s.)
All JSON functions currently throw an error if any of their
arguments are BLOBs because BLOBs are reserved
for a future enhancement in which BLOBs will store the binary encoding
for JSON.

3.1. JSON arguments


For functions that accept JSON as their first argument, that argument
can be a JSON object, array, number, string, or null.  SQLite numeric
values and NULL values are interpreted as JSON numbers and nulls, respectively.
SQLite text values can be understood as JSON objects, arrays, or strings.
If an SQLite text value that is not a well-formed JSON object, array, or
string is passed into JSON function, that function will usually throw
an error.  (Exceptions to this rule are json_valid() and
json_quote().)


For the purposes of determining validity, leading and trailing whitespace
on JSON inputs is ignored.  Interior whitespace is also ignored, in accordance
with the JSON spec.  These routines accept exactly the 
rfc-7159 JSON syntax
&mdash; no more and no less.



3.2. PATH arguments


For functions that accept PATH arguments, that PATH must be well-formed or
else the function will throw an error.
A well-formed PATH is a text value that begins with exactly one
'$' character followed by zero or more instances
of ".objectlabel" or "&#91;arrayindex&#93;".


The arrayindex is usually a non-negative integer N.  In
that case, the array element selected is the N-th element
of the array, starting with zero on the left.
The arrayindex can also be of the form "#-N"
in which case the element selected is the N-th from the
right.  The last element of the array is "#-1".  Think of
the "#" characters as the "number of elements in the array".  Then
the expression "#-1" evaluates to the integer that corresponds to 
the last entry in the array.  It is sometimes useful for the array
index to be just the # character, for example when appending
a value to an existing JSON array:


json_set('[0,1,2]','$[#]','new')
&rarr; '[0,1,2,"new"]'






3.3. VALUE arguments


For functions that accept "value" arguments (also shown as
"value1" and "value2"),
those arguments are usually understood
to be literal strings that are quoted and become JSON string values
in the result.  Even if the input value strings look like 
well-formed JSON, they are still interpreted as literal strings in the
result.


However, if a value argument comes directly from the result of another
JSON function or from the -> operator (but not the ->> operator),
then the argument is understood to be actual JSON and
the complete JSON is inserted rather than a quoted string.


For example, in the following call to json_object(), the value
argument looks like a well-formed JSON array.  However, because it is just
ordinary SQL text, it is interpreted as a literal string and added to the
result as a quoted string:


json_object('ex','[52,3.14159]')
&rarr; '{"ex":"[52,3.14159]"}'

json_object('ex',('52,3.14159]'->>'$'))
&rarr; '{"ex":"[52,3.14159]"}'





But if the value argument in the outer json_object() call is the
result of another JSON function like json() or json_array(), then
the value is understood to be actual JSON and is inserted as such:


json_object('ex',json('[52,3.14159]'))
&rarr; '{"ex":[52,3.14159]}'

json_object('ex',json_array(52,3.14159))
&rarr; '{"ex":[52,3.14159]}'

json_object('ex','[52,3.14159]'->'$')
&rarr; '{"ex":[52,3.14159]}'





To be clear: "json" arguments are always interpreted as JSON
regardless of where the value for that argument comes from.  But
"value" arguments are only interpreted as JSON if those arguments
come directly from another JSON function or the -> operator.

3.4. Compatibility


The current implementation of this JSON library uses a recursive descent
parser.  In order to avoid using excess stack space, any JSON input that has
more than 2000 levels of nesting is considered invalid.   Limits on nesting
depth are allowed for compatible implementations of JSON by
RFC-7159 section 9.


4. Function Details

The following sections provide additional detail on the operation of
the various JSON functions and operators:



4.1. The json() function

The json(X) function verifies that its argument X is a valid
JSON string and returns a minified version of that JSON string
(with all unnecessary whitespace removed).  If X is not a well-formed
JSON string, then this routine throws an error.

In other words, this function converts raw text that looks like
JSON into actual JSON so that it may be passed into the value argument
of some other json function and will be interpreted as JSON rather than
a string.  This function is not appropriate for testing whether or not
a particular string is well-formed JSON - use the json_valid() routine
below for that task.

If the argument X to json(X) contains JSON objects with duplicate
labels, then it is undefined whether or not the duplicates are
preserved.  The current implementation preserves duplicates.
However, future enhancements
to this routine may choose to silently remove duplicates.


Example:


json(' { "this" : "is", "a": [ "test" ] } ')
&rarr; '{"this":"is","a":["test"]}'






4.2. The json_array() function

The json_array() SQL function accepts zero or more arguments and
returns a well-formed JSON array that is composed from those arguments.
If any argument to json_array() is a BLOB then an error is thrown.

An argument with SQL type TEXT is normally converted into a quoted 
JSON string.  However, if the argument is the output from another json1
function, then it is stored as JSON.  This allows calls to json_array()
and json_object() to be nested.  The json() function can also
be used to force strings to be recognized as JSON.

Examples:


json_array(1,2,'3',4)
&rarr; '[1,2,"3",4]'

json_array('[1,2]')
&rarr; '["[1,2]"]'

json_array(json_array(1,2))
&rarr; '[[1,2]]'

json_array(1,null,'3','[4,5]','{"six":7.7}')
&rarr; '[1,null,"3","[4,5]","{\"six\":7.7}"]'

json_array(1,null,'3',json('[4,5]'),json('{"six":7.7}'))
&rarr; '[1,null,"3",[4,5],{"six":7.7}]'







4.3. The json_array_length() function

The json_array_length(X) function returns the number of elements
in the JSON array X, or 0 if X is some kind of JSON value other
than an array.  The json_array_length(X,P) locates the array at path P
within X and returns the length of that array, or 0 if path P locates
an element or X other than a JSON array, and NULL if path P does not
locate any element of X.  Errors are thrown if either X is not 
well-formed JSON or if P is not a well-formed path.

Examples:


json_array_length('[1,2,3,4]')
&rarr; 4

json_array_length('[1,2,3,4]', '$')
&rarr; 4

json_array_length('[1,2,3,4]', '$[2]')
&rarr; 0

json_array_length('{"one":[1,2,3]}')
&rarr; 0

json_array_length('{"one":[1,2,3]}', '$.one')
&rarr; 3

json_array_length('{"one":[1,2,3]}', '$.two')
&rarr; NULL







4.4. The json_extract() function

The json_extract(X,P1,P2,...) extracts and returns one or more 
values from the
well-formed JSON at X.  If only a single path P1 is provided, then the
SQL datatype of the result is NULL for a JSON null, INTEGER or REAL
for a JSON numeric value, an INTEGER zero for a JSON false value,
an INTEGER one for a JSON true value, the dequoted text for a 
JSON string value, and a text representation for JSON object and array values.
If there are multiple path arguments (P1, P2, and so forth) then this
routine returns SQLite text which is a well-formed JSON array holding
the various values.

Examples:


json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$')
&rarr; '{"a":2,"c":[4,5,{"f":7}]}'

json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c')
&rarr; '[4,5,{"f":7}]'

json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]')
&rarr; '{"f":7}'

json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2].f')
&rarr; 7

json_extract('{"a":2,"c":[4,5],"f":7}','$.c','$.a')
&rarr; '[[4,5],2]'

json_extract('{"a":2,"c":[4,5],"f":7}','$.c[#-1]')
&rarr; 5

json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x')
&rarr; NULL

json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x', '$.a')
&rarr; '[null,2]'

json_extract('{"a":"xyz"}', '$.a')
&rarr; 'xyz'

json_extract('{"a":null}', '$.a')
&rarr; NULL




There is a subtle incompatibility between the json_extract() function
in SQLite and the json_extract() function in MySQL.  The MySQL version
of json_extract() always returns JSON.  The SQLite version of
json_extract() only returns JSON if there are two or more PATH arguments
(because the result is then a JSON array) or if the single PATH argument
references an array or object.  In SQLite, if json_extract() has only
a single PATH argument and that PATH references a JSON null or a string
or a numeric value, then json_extract() returns the corresponding SQL
NULL, TEXT, INTEGER, or REAL value.

The difference between MySQL json_extract() and SQLite json_extract()
really only stands out when accessing individual values within the JSON
that are strings or NULLs.  The following table demonstrates the difference:



OperationSQLite ResultMySQL Result
json_extract('{"a":null,"b":"xyz"}','$.a')NULL'null'
json_extract('{"a":null,"b":"xyz"}','$.b')'xyz''"xyz"'




4.5. The -> and ->> operators

Beginning with SQLite version 3.38.0 (2022-02-22), the ->
and ->> operators are available for extracting subcomponents of JSON.
The SQLite implementation of the -> and ->> operators strive to be
compatible with both MySQL and PostgreSQL.
The -> and ->> operators take a JSON string
as their left operand and a PATH expression or object field
label or array index as their right operand.  The -> operator
returns a JSON representation of the selected subcomponent or NULL if that
subcomponent does not exist.  The ->> operator returns an SQL TEXT,
INTEGER, REAL, or NULL value that represents the selected subcomponent,
or NULL if the subcomponent does not exist.

Both the -> and ->> operators select the same subcomponent
of the JSON to their left.  The difference is that -> always returns a
JSON representation of that subcomponent and the ->> operator always
returns an SQL representation of that subcomponent.  Thus, these operators
are subtly different from a two-argument json_extract() function call.
A call to json_extract() with two arguments will return a JSON representation
of the subcomponent if and only if the subcomponent is a JSON array or
object, and will return an SQL representation of the subcomponent if the
subcomponent is a JSON null, string, or numeric value.

The right-hand operand to the -> and ->> operators can
be a well-formed JSON path expression.  This is the form used by MySQL.
For compatibility with PostgreSQL,
the -> and ->> operators also accept a text label or
integer as their right-hand operand.  If the right operand is a text
label X, then it is interpreted as the JSON path '$.X'.  If the right
operand is an integer value N, then it is interpreted as the JSON path '$[N]'.

Examples:


'{"a":2,"c":[4,5,{"f":7}]}' -> '$'
&rarr; '{"a":2,"c":[4,5,{"f":7}]}'

'{"a":2,"c":[4,5,{"f":7}]}' -> '$.c'
&rarr; '[4,5,{"f":7}]'

'{"a":2,"c":[4,5,{"f":7}]}' -> 'c'
&rarr; '[4,5,{"f":7}]'

'{"a":2,"c":[4,5,{"f":7}]}' -> '$.c[2]'
&rarr; '{"f":7}'

'{"a":2,"c":[4,5,{"f":7}]}' -> '$.c[2].f'
&rarr; '7'

'{"a":2,"c":[4,5],"f":7}' -> '$.c[#-1]'
&rarr; '5'

'{"a":2,"c":[4,5,{"f":7}]}' -> '$.x'
&rarr; NULL

'[11,22,33,44]' -> 3
&rarr; '44'

'[11,22,33,44]' ->> 3
&rarr; 44

'{"a":"xyz"}' -> '$.a'
&rarr; '"xyz"'

'{"a":"xyz"}' ->> '$.a'
&rarr; 'xyz'

'{"a":null}' -> '$.a'
&rarr; 'null'

'{"a":null}' ->> '$.a'
&rarr; NULL










4.6. The json_insert(), json_replace, and json_set() functions

The json_insert(), json_replace, and json_set() functions all take
a single JSON value as their first argument followed by zero or more
pairs of path and value arguments, and return a new JSON string formed
by updating the input JSON by the path/value pairs.  The functions
differ only in how they deal with creating new values and overwriting
preexisting values.




FunctionOverwrite if already exists?Create if does not exist?

json_insert()NoYes

json_replace()YesNo

json_set()YesYes


The json_insert(), json_replace(), and json_set() functions always
take an odd number of arguments.  The first argument is always the original
JSON to be edited.  Subsequent arguments occur in pairs with the first
element of each pair being a path and the second element being the value
to insert or replace or set on that path.

Edits occur sequentially from left to right.  Changes caused by
prior edits can affect the path search for subsequent edits.

If the value of a path/value pair is an SQLite TEXT value, then it
is normally inserted as a quoted JSON string, even if the string looks
like valid JSON.  However, if the value is the result of another
json1 function (such as json() or json_array() or json_object())
or if it is the result of the -> operator,
then it is interpreted as JSON and is inserted as JSON retaining all
of its substructure.  Values that are the result of the ->> operator
are always interpreted as TEXT and are inserted as a JSON string even
if they look like valid JSON.

These routines throw an error if the first JSON argument is not
well-formed or if any PATH argument is not well-formed or if any
argument is a BLOB.

To append an element onto the end of an array, using json_insert()
with an array index of "#".  Examples:


json_insert('[1,2,3,4]','$[#]',99)
&rarr; '[1,2,3,4,99]'

json_insert('[1,[2,3],4]','$[1][#]',99)
&rarr; '[1,[2,3,99],4]'




Other examples:


json_insert('{"a":2,"c":4}', '$.a', 99)
&rarr; '{"a":2,"c":4}'

json_insert('{"a":2,"c":4}', '$.e', 99)
&rarr; '{"a":2,"c":4,"e":99}'

json_replace('{"a":2,"c":4}', '$.a', 99)
&rarr; '{"a":99,"c":4}'

json_replace('{"a":2,"c":4}', '$.e', 99)
&rarr; '{"a":2,"c":4}'

json_set('{"a":2,"c":4}', '$.a', 99)
&rarr; '{"a":99,"c":4}'

json_set('{"a":2,"c":4}', '$.e', 99)
&rarr; '{"a":2,"c":4,"e":99}'

json_set('{"a":2,"c":4}', '$.c', '[97,96]')
&rarr; '{"a":2,"c":"[97,96]"}'

json_set('{"a":2,"c":4}', '$.c', json('[97,96]'))
&rarr; '{"a":2,"c":[97,96]}'

json_set('{"a":2,"c":4}', '$.c', json_array(97,96))
&rarr; '{"a":2,"c":[97,96]}'






4.7. The json_object() function

The json_object() SQL function accepts zero or more pairs of arguments
and returns a well-formed JSON object that is composed from those arguments.
The first argument of each pair is the label and the second argument of
each pair is the value.
If any argument to json_object() is a BLOB then an error is thrown.

The json_object() function currently allows duplicate labels without
complaint, though this might change in a future enhancement.

An argument with SQL type TEXT it is normally converted into a quoted 
JSON string even if the input text is well-formed JSON.  
However, if the argument is the direct result from another JSON
function or the -> operator (but not the ->> operator), 
then it is treated as JSON and all of its JSON type information
and substructure is preserved.  This allows calls to json_object()
and json_array() to be nested.  The json() function can also
be used to force strings to be recognized as JSON.

Examples:


json_object('a',2,'c',4)
&rarr; '{"a":2,"c":4}'

json_object('a',2,'c','{e:5}')
&rarr; '{"a":2,"c":"{e:5}"}'

json_object('a',2,'c',json_object('e',5))
&rarr; '{"a":2,"c":{"e":5}}'






4.8. The json_patch() function

The json_patch(T,P) SQL function runs the
RFC-7396 MergePatch algorithm
to apply patch P against input T.  The patched copy of T is returned.

MergePatch can add, modify, or delete elements of a JSON Object,
and so for JSON Objects, the json_patch() routine is a generalized
replacement for json_set() and json_remove().  However, MergePatch
treats JSON Array objects as atomic.  MergePatch cannot append to an
Array nor modify individual elements of an Array.  It can only insert,
replace, or delete the whole Array as a single unit.  Hence, json_patch()
is not as useful when dealing with JSON that includes Arrays,
especially Arrays with lots of substructure.

Examples:


json_patch('{"a":1,"b":2}','{"c":3,"d":4}')
&rarr; '{"a":1,"b":2,"c":3,"d":4}'

json_patch('{"a":[1,2],"b":2}','{"a":9}')
&rarr; '{"a":9,"b":2}'

json_patch('{"a":[1,2],"b":2}','{"a":null}')
&rarr; '{"b":2}'

json_patch('{"a":1,"b":2}','{"a":9,"b":null,"c":8}')
&rarr; '{"a":9,"c":8}'

json_patch('{"a":{"x":1,"y":2},"b":3}','{"a":{"y":9},"c":8}')
&rarr; '{"a":{"x":1,"y":9},"b":3,"c":8}'






4.9. The json_remove() function

The json_remove(X,P,...) function takes a single JSON value as its
first argument followed by zero or more path arguments.
The json_remove(X,P,...) function returns
a copy of the X parameter with all the elements 
identified by path arguments removed.  Paths that select elements
not found in X are silently ignored.

Removals occurs sequentially from left to right.  Changes caused by
prior removals can affect the path search for subsequent arguments.

If the json_remove(X) function is called with no path arguments,
then it returns the input X reformatted, with excess whitespace
removed.

The json_remove() function throws an error if the first argument
is not well-formed JSON or if any later argument is not a well-formed
path, or if any argument is a BLOB.

Examples:


json_remove('[0,1,2,3,4]','$[2]')
&rarr; '[0,1,3,4]'

json_remove('[0,1,2,3,4]','$[2]','$[0]')
&rarr; '[1,3,4]'

json_remove('[0,1,2,3,4]','$[0]','$[2]')
&rarr; '[1,2,4]'

json_remove('[0,1,2,3,4]','$[#-1]','$[0]')
&rarr; '[1,2,3]'

json_remove('{"x":25,"y":42}')
&rarr; '{"x":25,"y":42}'

json_remove('{"x":25,"y":42}','$.z')
&rarr; '{"x":25,"y":42}'

json_remove('{"x":25,"y":42}','$.y')
&rarr; '{"x":25}'

json_remove('{"x":25,"y":42}','$')
&rarr; NULL






4.10. The json_type() function

The json_type(X) function returns the "type" of the outermost element
of X.  The json_type(X,P) function returns the "type" of the element
in X that is selected by path P.  The "type" returned by json_type() is
one of the following SQL text values:
'null', 'true', 'false', 'integer', 'real', 'text', 'array', or 'object'.
If the path P in json_type(X,P) selects an element that does not exist
in X, then this function returns NULL.

The json_type() function throws an error if any of its arguments is
not well-formed or is a BLOB.

Examples:


json_type('{"a":[2,3.5,true,false,null,"x"]}')
&rarr; 'object'

json_type('{"a":[2,3.5,true,false,null,"x"]}','$')
&rarr; 'object'

json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a')
&rarr; 'array'

json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[0]')
&rarr; 'integer'

json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[1]')
&rarr; 'real'

json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[2]')
&rarr; 'true'

json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[3]')
&rarr; 'false'

json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[4]')
&rarr; 'null'

json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[5]')
&rarr; 'text'

json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[6]')
&rarr; NULL






4.11. The json_valid() function

The json_valid(X) function return 1 if the argument X is well-formed
JSON and return 0 if the argument X is not well-formed JSON.

Examples:


json_valid('{"x":35}')
&rarr; 1

json_valid('{"x":35')
&rarr; 0






4.12. The json_quote() function

The json_quote(X) function converts the SQL value X (a number or a
string) into its corresponding JSON representation.  If X is a JSON value
returned by another JSON function, then this function is a no-op.

Examples:


json_quote(3.14159)
&rarr; 3.14159

json_quote('verdant')
&rarr; '"verdant"'

json_quote('[1]')
&rarr; '"[1]"'

json_quote(json('[1]'))
&rarr; '[1]'

json_quote('[1,')
&rarr; '"[1"'







4.13. The json_group_array() and json_group_object()
aggregate SQL functions

The json_group_array(X) function is an 
aggregate SQL function that returns a JSON array
comprised of all X values in the aggregation.
Similarly, the json_group_object(NAME,VALUE) function returns a JSON object
comprised of all NAME/VALUE pairs in the aggregation.






4.14. The json_each() and json_tree() table-valued functions

The json_each(X) and json_tree(X) table-valued functions walk the
JSON value provided as their first argument and return one row for each
element.  The json_each(X) function only walks the immediate children
of the top-level array or object,
or just the top-level element itself if the top-level
element is a primitive value.
The json_tree(X) function recursively walks through the
JSON substructure starting with the top-level element.  

The json_each(X,P) and json_tree(X,P) functions work just like
their one-argument counterparts except that they treat the element
identified by path P as the top-level element.

The schema for the table returned by json_each() and json_tree() is
as follows:


CREATE TABLE json_tree(
    key ANY,             -- key for current element relative to its parent
    value ANY,           -- value for the current element
    type TEXT,           -- 'object','array','string','integer', etc.
    atom ANY,            -- value for primitive types, null for array & object
    id INTEGER,          -- integer ID for this element
    parent INTEGER,      -- integer ID for the parent of this element
    fullkey TEXT,        -- full path describing the current element
    path TEXT,           -- path to the container of the current row
    json JSON HIDDEN,    -- 1st input parameter: the raw JSON
    root TEXT HIDDEN     -- 2nd input parameter: the PATH at which to start
);



The "key" column is the integer array index for elements of a JSON array 
and the text label for elements of a JSON object.  The key column is
NULL in all other cases.


The "atom" column is the SQL value corresponding to primitive elements - 
elements other than JSON arrays and objects.  The "atom" column is NULL
for a JSON array or object.  The "value" column is the same as the
"atom" column for primitive JSON elements but takes on the text JSON value
for arrays and objects.


The "type" column is an SQL text value taken from ('null', 'true', 'false',
'integer', 'real', 'text', 'array', 'object') according to the type of
the current JSON element.


The "id" column is an integer that identifies a specific JSON element
within the complete JSON string.  The "id" integer is an internal housekeeping
number, the computation of which might change in future releases.  The
only guarantee is that the "id" column will be different for every row.


The "parent" column is always NULL for json_each().
For json_tree(),
the "parent" column is the "id" integer for the parent of the current
element, or NULL for the top-level JSON element or the element identified
by the root path in the second argument.


The "fullkey" column is a text path that uniquely identifies the current
row element within the original JSON string.  The complete key to the
true top-level element is returned even if an alternative starting point
is provided by the "root" argument.


The "path" column is the path to the array or object container that holds 
the current row, or the path to the current row in the case where the 
iteration starts on a primitive type and thus only provides a single
row of output.

4.14.1. Examples using json_each() and json_tree()

Suppose the table "CREATE TABLE user(name,phone)" stores zero or
more phone numbers as a JSON array object in the user.phone field.
To find all users who have any phone number with a 704 area code:


SELECT DISTINCT user.name
  FROM user, json_each(user.phone)
 WHERE json_each.value LIKE '704-%';


Now suppose the user.phone field contains plain text if the user
has only a single phone number and a JSON array if the user has multiple
phone numbers.  The same question is posed: "Which users have a phone number
in the 704 area code?"  But now the json_each() function can only be called
for those users that have two or more phone numbers since json_each()
requires well-formed JSON as its first argument:


SELECT name FROM user WHERE phone LIKE '704-%'
UNION
SELECT user.name
  FROM user, json_each(user.phone)
 WHERE json_valid(user.phone)
   AND json_each.value LIKE '704-%';


Consider a different database with "CREATE TABLE big(json JSON)".
To see a complete line-by-line decomposition of the data:


SELECT big.rowid, fullkey, value
  FROM big, json_tree(big.json)
 WHERE json_tree.type NOT IN ('object','array');


In the previous, the "type NOT IN ('object','array')" term of the
WHERE clause suppresses containers and only lets through leaf elements.
The same effect could be achieved this way:


SELECT big.rowid, fullkey, atom
  FROM big, json_tree(big.json)
 WHERE atom IS NOT NULL;


Suppose each entry in the BIG table is a JSON object 
with a '$.id' field that is a unique identifier
and a '$.partlist' field that can be a deeply nested object.
You want to find the id of every entry that contains one
or more references to uuid '6fa5181e-5721-11e5-a04e-57f3d7b32808' anywhere
in its '$.partlist'.


SELECT DISTINCT json_extract(big.json,'$.id')
  FROM big, json_tree(big.json, '$.partlist')
 WHERE json_tree.key='uuid'
   AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';

This page last modified on  2022-06-24 16:56:23 UTC


c2: Partial Indexes
c5: partialindex.html
c4:
1. Introduction


A partial index is an index over a subset of the rows of a table.



In ordinary indexes, there is exactly one entry in the index for every
row in the table.  In partial indexes, only some subset of the rows in the
table have corresponding index entries.  For example, a partial index might
omit entries for which the column being indexed is NULL.  When used 
judiciously, partial indexes can result in smaller database files and
improvements in both query and write performance.


2. Creating Partial Indexes


Create a partial index by adding a WHERE clause to the end of an 
ordinary CREATE INDEX statement.


create-index-stmt:
hide
 
 

expr:
show
 
 

filter-clause:
show
 
 


literal-value:
show
 
 


over-clause:
show
 
 

frame-spec:
show
 
 


ordering-term:
show
 
 



raise-function:
show
 
 


select-stmt:
show
 
 

common-table-expression:
show
 
 


compound-operator:
show
 
 


join-clause:
show
 
 

join-constraint:
show
 
 


join-operator:
show
 
 



ordering-term:
show
 
 


result-column:
show
 
 


table-or-subquery:
show
 
 


window-defn:
show
 
 

frame-spec:
show
 
 




type-name:
show
 
 

signed-number:
show
 
 




indexed-column:
show
 
 






Any index that includes the WHERE clause at the end is considered to be
a partial index.  Indexes that omit the WHERE clause (or indexes that
are created by UNIQUE or PRIMARY KEY constraints inside of CREATE TABLE
statements) are ordinary full indexes.



The expression following the WHERE clause may contain operators,
literal values, and names of columns in the table being indexed.
The WHERE clause may not contain subqueries, references to other
tables, non-deterministic functions, or bound parameters.


Only rows of the table for which the WHERE clause evaluates to true
are included in the index.  If the WHERE clause expression evaluates 
to NULL or to false for some rows of the table, then those rows are omitted 
from the index.



The columns referenced in the WHERE clause of a partial index can be
any of the columns in the table, not just columns that happen to be
indexed.  However, it is very common for the WHERE clause
expression of a partial index to be a simple expression on the column
being indexed.  The following is a typical example:

CREATE INDEX po_parent ON purchaseorder(parent_po) WHERE parent_po IS NOT NULL;


In the example above, if most purchase orders do not have a "parent"
purchase order, then most parent_po values will be NULL.  That means only
a small subset of the rows in the purchaseorder table will be indexed.
Hence the index will take up much less space.  And changes to the original
purchaseorder table will run faster since the po_parent index only needs
to be updated for those exceptional rows where parent_po is not NULL.
But the index is still useful for querying.  In particular, if one wants
to know all "children" of a particular purchase order "?1", the query
would be:

SELECT po_num FROM purchaseorder WHERE parent_po=?1;


The query above will use the po_parent index to help find the answer,
since the po_parent index contains entries for all rows of interest.
Note that since po_parent is smaller than a full index, the query will
likely run faster too.

2.1. Unique Partial Indexes

A partial index definition may include the UNIQUE keyword.  If it
does, then SQLite requires every entry in the index to be unique.
This provides a mechanism for enforcing uniqueness across some subset of
the rows in a table.

For example, suppose you have a database of the members of a large
organization where each person is assigned to a particular "team".  
Each team has a "leader" who is also a member of that team.  The
table might look something like this:

CREATE TABLE person(
  person_id       INTEGER PRIMARY KEY,
  team_id         INTEGER REFERENCES team,
  is_team_leader  BOOLEAN,
  -- other fields elided
);


The team_id field cannot be unique because there are usually multiple people
on the same team.  One cannot make the combination of team_id and is_team_leader
unique since there are usually multiple non-leaders on each team.  The
solution to enforcing one leader per team is to create a unique index
on team_id but restricted to those entries for which is_team_leader is
true:

CREATE UNIQUE INDEX team_leader ON person(team_id) WHERE is_team_leader;


Coincidentally, that same index is useful for locating the team leader
of a particular team:

SELECT person_id FROM person WHERE is_team_leader AND team_id=?1;


3. Queries Using Partial Indexes

Let X be the expression in the WHERE clause of a partial
index, and let W be the WHERE clause of a query that uses the
table that is indexed.  Then, the query is permitted to use 
the partial index if W&#x21d2;X, where the &#x21d2; operator
(usually pronounced "implies") is the logic operator 
equivalent to "X or not W".
Hence, determining whether or not a partial index
is usable in a particular query reduces to proving a theorem in
first-order logic.

SQLite does not have a sophisticated theorem
prover with which to determine W&#x21d2;X.  Instead, SQLite uses 
two simple rules to find the common cases where W&#x21d2;X is true, and
it assumes all the other cases are false.  The rules used by SQLite
are these:


If W is AND-connected terms and X is
OR-connected terms and if any term of W
appears as a term of X, then the partial index is usable.

For example, let the index be
CREATE INDEX ex1 ON tab1(a,b) WHERE a=5 OR b=6;

And let the query be:
SELECT * FROM tab1 WHERE b=6 AND a=7; -- uses partial index

Then the index is usable by the query because the "b=6" term appears
in both the index definition and in the query.  Remember: terms in the
index should be OR-connected and terms in the query should be AND-connected.

The terms in W and X must match exactly.  SQLite does not
do algebra to try to get them to look the same.
The term "b=6" does not match "b=3+3" or "b-6=0" or "b BETWEEN 6 AND 6".
"b=6" will match to "6=b" as long as "b=6" is on the index and "6=b" is
in the query.  If a term of the form "6=b" appears in the index, it will
never match anything.

If a term in X is of the form "z IS NOT NULL" and if a term in
       W is a comparison operator on "z" other than "IS", then those
       terms match.

Example:  Let the index be
CREATE INDEX ex2 ON tab2(b,c) WHERE c IS NOT NULL;

Then any query that uses operators =, &lt;, &gt;, &lt;=, &gt;=, &lt;&gt;,
IN, LIKE, or GLOB on column "c" 
would be usable with the partial index because those
comparison operators are only true if "c" is not NULL.  So the following
query could use the partial index:
SELECT * FROM tab2 WHERE b=456 AND c&lt;&gt;0;  -- uses partial index

But the next query can not use the partial index:
SELECT * FROM tab2 WHERE b=456;  -- cannot use partial index

The latter query can not use the partial index because there might be
rows in the table with b=456 and where c is NULL.  But those rows would
not be in the partial index.


These two rules describe how the query planner for SQLite works as of
this writing (2013-08-01).  And the rules above will always be honored.
However, future versions of SQLite might incorporate a better theorem prover
that can find other cases where W&#x21d2;X is true and thus may
find more instances where partial indexes are useful.

4. Supported Versions


Partial indexes have been supported in SQLite since version 3.8.0
(2013-08-26).


Database files that contain partial indices are not readable or writable
by versions of SQLite prior to 3.8.0.  However, a database file created
by SQLite 3.8.0 is still readable and writable by prior versions as long
as its schema contains no partial indexes.  A database that is unreadable
by legacy versions of SQLite can be made readable simply by running
DROP INDEX on the partial indexes.
This page last modified on  2022-01-20 21:38:08 UTC


c2: SQLite Backup API
c5: backup.html
c4:
Using the SQLite Online Backup API


  Historically, backups (copies) of SQLite databases have been created
  using the following method:


   Establish a shared lock on the database file using the SQLite API (i.e.
       the shell tool).
   Copy the database file using an external tool (for example the unix 'cp'
       utility or the DOS 'copy' command).
   Relinquish the shared lock on the database file obtained in step 1.



  This procedure works well in many scenarios and is usually very
  fast. However, this technique has the following shortcomings:


   Any database clients wishing to write to the database file while a
       backup is being created must wait until the shared lock is
       relinquished.

   It cannot be used to copy data to or from in-memory databases.

   If a power failure or operating system failure occurs while copying
       the database file the backup database may be corrupted following
       system recovery.



  The Online Backup API was created to 
  address these concerns. The online backup API allows the contents of
  one database to be copied into another database file, replacing any 
  original contents of the target database. The copy operation may be 
  done incrementally, in which case the source database does not need
  to be locked for the duration of the copy, only for the brief periods
  of time when it is actually being read from. This allows other database
  users to continue without excessive delays while a backup of an online
  database is made.

  The effect of completing the backup call sequence is to make the
  destination a bit-wise identical copy of the source database as it
  was when the copying commenced. (The destination becomes a "snapshot.")


  The online backup API is documented here.
  The remainder of this page contains two C language examples illustrating 
  common uses of the API and discussions thereof. Reading these examples
  is no substitute for reading the API documentation!


  Update: The VACUUM INTO command introduced in 
  SQLite version 3.27.0 (2019-02-07) can serve as an
  alternative to the backup API.

Example 1: Loading and Saving In-Memory Databases


/*
** This function is used to load the contents of a database file on disk 
** into the "main" database of open database connection pInMemory, or
** to save the current contents of the database opened by pInMemory into
** a database file on disk. pInMemory is probably an in-memory database, 
** but this function will also work fine if it is not.
**
** Parameter zFilename points to a nul-terminated string containing the
** name of the database file on disk to load from or save to. If parameter
** isSave is non-zero, then the contents of the file zFilename are 
** overwritten with the contents of the database opened by pInMemory. If
** parameter isSave is zero, then the contents of the database opened by
** pInMemory are replaced by data loaded from the file zFilename.
**
** If the operation is successful, SQLITE_OK is returned. Otherwise, if
** an error occurs, an SQLite error code is returned.
*/
int loadOrSaveDb(sqlite3 *pInMemory, const char *zFilename, int isSave){
  int rc;                   /* Function return code */
  sqlite3 *pFile;           /* Database connection opened on zFilename */
  sqlite3_backup *pBackup;  /* Backup object used to copy data */
  sqlite3 *pTo;             /* Database to copy to (pFile or pInMemory) */
  sqlite3 *pFrom;           /* Database to copy from (pFile or pInMemory) */

  /* Open the database file identified by zFilename. Exit early if this fails
  ** for any reason. */
  rc = sqlite3_open(zFilename, &pFile);
  if( rc==SQLITE_OK ){

    /* If this is a 'load' operation (isSave==0), then data is copied
    ** from the database file just opened to database pInMemory. 
    ** Otherwise, if this is a 'save' operation (isSave==1), then data
    ** is copied from pInMemory to pFile.  Set the variables pFrom and
    ** pTo accordingly. */
    pFrom = (isSave ? pInMemory : pFile);
    pTo   = (isSave ? pFile     : pInMemory);

    /* Set up the backup procedure to copy from the "main" database of 
    ** connection pFile to the main database of connection pInMemory.
    ** If something goes wrong, pBackup will be set to NULL and an error
    ** code and message left in connection pTo.
    **
    ** If the backup object is successfully created, call backup_step()
    ** to copy data from pFile to pInMemory. Then call backup_finish()
    ** to release resources associated with the pBackup object.  If an
    ** error occurred, then an error code and message will be left in
    ** connection pTo. If no error occurred, then the error code belonging
    ** to pTo is set to SQLITE_OK.
    */
    pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
    if( pBackup ){
      (void)sqlite3_backup_step(pBackup, -1);
      (void)sqlite3_backup_finish(pBackup);
    }
    rc = sqlite3_errcode(pTo);
  }

  /* Close the database connection opened on database file zFilename
  ** and return the result of this function. */
  (void)sqlite3_close(pFile);
  return rc;
}




  The C function to the right demonstrates one of the simplest,
  and most common, uses of the backup API: loading and saving the contents
  of an in-memory database to a file on disk. The backup API is used as
  follows in this example:

  
    Function sqlite3_backup_init() is called to create an sqlite3_backup
        object to copy data between the two databases (either from a file and
        into the in-memory database, or vice-versa).
    Function sqlite3_backup_step() is called with a parameter of 
        -1 to copy the entire source database to the destination.
    Function sqlite3_backup_finish() is called to clean up resources
        allocated by sqlite3_backup_init().
  

Error handling


  If an error occurs in any of the three main backup API routines
  then the error code and message are attached to
  the destination database connection.
  Additionally, if
  sqlite3_backup_step() encounters an error, then the error code is returned
  by both the sqlite3_backup_step() call itself, and by the subsequent call
  to sqlite3_backup_finish(). So a call to sqlite3_backup_finish()
  does not overwrite an error code stored in the destination
  database connection by sqlite3_backup_step().  This feature
  is used in the example code to reduce amount of error handling required.
  The return values of the sqlite3_backup_step() and sqlite3_backup_finish()
  calls are ignored and the error code indicating the success or failure of
  the copy operation collected from the destination database connection
  afterward.

Possible Enhancements


  The implementation of this function could be enhanced in at least two ways:

  
     Failing to obtain the lock on database file zFilename (an SQLITE_BUSY
         error) could be handled, and
     Cases where the page-sizes of database pInMemory and zFilename are
         different could be handled better.
  


  Since database zFilename is a file on disk, then it may be accessed 
  externally by another process. This means that when the call to
  sqlite3_backup_step() attempts to read from or write data to it, it may
  fail to obtain the required file lock. If this happens, this implementation
  will fail, returning SQLITE_BUSY immediately. The solution would be to
  register a busy-handler callback or 
  timeout with database connection pFile 
  using sqlite3_busy_handler() or sqlite3_busy_timeout()
  as soon as it is opened. If it fails to obtain a required lock immediately,
  sqlite3_backup_step() uses any registered busy-handler callback or timeout
  in the same way as sqlite3_step() or sqlite3_exec() does.


  Usually, it does not matter if the page-sizes of the source database and the
  destination database are different before the contents of the destination
  are overwritten. The page-size of the destination database is simply changed
  as part of the backup operation. The exception is if the destination database
  happens to be an in-memory database. In this case, if the page sizes
  are not the same at the start of the backup operation, then the operation
  fails with an SQLITE_READONLY error. Unfortunately, this could occur when
  loading a database image from a file into an in-memory database using
  function loadOrSaveDb().


  However, if in-memory database pInMemory has just been opened (and is 
  therefore completely empty) before being passed to function loadOrSaveDb(), 
  then it is still possible to change its page size using an SQLite "PRAGMA
  page_size" command. Function loadOrSaveDb() could detect this case, and
  attempt to set the page-size of the in-memory database to the page-size
  of database zFilename before invoking the online backup API functions.
  
Example 2: Online Backup of a Running Database


/*
** Perform an online backup of database pDb to the database file named
** by zFilename. This function copies 5 database pages from pDb to
** zFilename, then unlocks pDb and sleeps for 250 ms, then repeats the
** process until the entire database is backed up.
** 
** The third argument passed to this function must be a pointer to a progress
** function. After each set of 5 pages is backed up, the progress function
** is invoked with two integer parameters: the number of pages left to
** copy, and the total number of pages in the source file. This information
** may be used, for example, to update a GUI progress bar.
**
** While this function is running, another thread may use the database pDb, or
** another process may access the underlying database file via a separate 
** connection.
**
** If the backup process is successfully completed, SQLITE_OK is returned.
** Otherwise, if an error occurs, an SQLite error code is returned.
*/
int backupDb(
  sqlite3 *pDb,               /* Database to back up */
  const char *zFilename,      /* Name of file to back up to */
  void(*xProgress)(int, int)  /* Progress function to invoke */     
){
  int rc;                     /* Function return code */
  sqlite3 *pFile;             /* Database connection opened on zFilename */
  sqlite3_backup *pBackup;    /* Backup handle used to copy data */

  /* Open the database file identified by zFilename. */
  rc = sqlite3_open(zFilename, &pFile);
  if( rc==SQLITE_OK ){

    /* Open the sqlite3_backup object used to accomplish the transfer */
    pBackup = sqlite3_backup_init(pFile, "main", pDb, "main");
    if( pBackup ){

      /* Each iteration of this loop copies 5 database pages from database
      ** pDb to the backup database. If the return value of backup_step()
      ** indicates that there are still further pages to copy, sleep for
      ** 250 ms before repeating. */
      do {
        rc = sqlite3_backup_step(pBackup, 5);
        xProgress(
            sqlite3_backup_remaining(pBackup),
            sqlite3_backup_pagecount(pBackup)
        );
        if( rc==SQLITE_OK || rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
          sqlite3_sleep(250);
        }
      } while( rc==SQLITE_OK || rc==SQLITE_BUSY || rc==SQLITE_LOCKED );

      /* Release resources allocated by backup_init(). */
      (void)sqlite3_backup_finish(pBackup);
    }
    rc = sqlite3_errcode(pFile);
  }
  
  /* Close the database connection opened on database file zFilename
  ** and return the result of this function. */
  (void)sqlite3_close(pFile);
  return rc;
}




  The function presented in the previous example copies the entire source
  database in one call to sqlite3_backup_step(). This requires holding a 
  read-lock on the source database file for the duration of the operation,
  preventing any other database user from writing to the database. It also
  holds the mutex associated with database pInMemory throughout the copy,
  preventing any other thread from using it. The C function in this section,
  designed to be called by a background thread or process for creating a 
  backup of an online database, avoids these problems using the following 
  approach:

  
    Function sqlite3_backup_init() is called to create an sqlite3_backup
        object to copy data from database pDb to the backup database file 
        identified by zFilename.
    Function sqlite3_backup_step() is called with a parameter of 5 to
        copy 5 pages of database pDb to the backup database (file zFilename).
    If there are still more pages to copy from database pDb, then the
        function sleeps for 250 milliseconds (using the sqlite3_sleep()
        utility) and then returns to step 2.
    Function sqlite3_backup_finish() is called to clean up resources
        allocated by sqlite3_backup_init().
  

File and Database Connection Locking


  During the 250 ms sleep in step 3 above, no read-lock is held on the database
  file and the mutex associated with pDb is not held. This allows other threads
  to use database connection pDb and other connections to write to the
  underlying database file. 


  If another thread or process writes to the source database while this 
  function is sleeping, then SQLite detects this and usually restarts the 
  backup process when sqlite3_backup_step() is next called. There is one 
  exception to this rule: If the source database is not an in-memory database,
  and the write is performed from within the same process as the backup
  operation and uses the same database handle (pDb), then the destination
  database (the one opened using connection pFile) is automatically updated
  along with the source. The backup process may then be continued after the 
  sqlite3_sleep() call returns as if nothing had happened. 


  Whether or not the backup process is restarted as a result of writes to
  the source database mid-backup, the user can be sure that when the backup
  operation is completed the backup database contains a consistent and 
  up-to-date snapshot of the original. However:

  
     Writes to an in-memory source database, or writes to a file-based 
         source database by an external process or thread using a 
         database connection other than pDb are significantly more expensive 
         than writes made to a file-based source database using pDb (as the
         entire backup operation must be restarted in the former two cases).

     If the backup process is restarted frequently enough it may never
         run to completion and the backupDb() function may never return.
  
 
backup_remaining() and backup_pagecount()


  The backupDb() function uses the sqlite3_backup_remaining() and
  sqlite3_backup_pagecount() functions to report its progress via the
  user-supplied xProgress() callback. Function sqlite3_backup_remaining()
  returns the number of pages left to copy and sqlite3_backup_pagecount()
  returns the total number of pages in the source database (in this case 
  the database opened by pDb). So the percentage completion of the process
  may be calculated as:


  Completion = 100% * (pagecount() - remaining()) / pagecount()


  The sqlite3_backup_remaining() and sqlite3_backup_pagecount() APIs report
  values stored by the previous call to sqlite3_backup_step(), they do not
  actually inspect the source database file. This means that if the source
  database is written to by another thread or process after the call to
  sqlite3_backup_step() returns but before the values returned by
  sqlite3_backup_remaining() and sqlite3_backup_pagecount() are used, the 
  values may be technically incorrect. This is not usually a problem.



This page last modified on  2021-12-10 14:23:30 UTC


c2: Distinctive Features Of SQLite
c5: different.html
c4:
Distinctive Features Of SQLite


This page highlights some of the characteristics of SQLite that are
unusual and which make SQLite different from many other SQL
database engines.



Zero-Configuration

  SQLite does not need to be "installed" before it is used. 
  There is no "setup" procedure.  There is no
  server process that needs to be started, stopped, or configured.
  There is
  no need for an administrator to create a new database instance or assign
  access permissions to users.
  SQLite uses no configuration files.
  Nothing needs to be done to tell the system that SQLite is running.
  No actions are required to recover after a system crash or power failure.
  There is nothing to troubleshoot.
  
  SQLite just works.
  
  Other more familiar database engines run great once you get them going.
  But doing the initial installation and configuration can be
  intimidatingly complex.


Serverless

  
  (See also the serverless documentation page.)
  
  Most SQL database engines are implemented as a separate server
  process.  Programs that want to access the database communicate
  with the server using some kind of interprocess communication
  (typically TCP/IP) to send requests to the server and to receive
  back results.  SQLite does not work this way.  With SQLite, the
  process that wants to access the database reads and writes
  directly from the database files on disk.  There is no intermediary
  server process.
  
  There are advantages and disadvantages to being serverless.  The
  main advantage is that there is no separate server process
  to install, setup, configure, initialize, manage, and troubleshoot.
  This is one reason why SQLite is a "zero-configuration" database
  engine.  Programs that use SQLite require no administrative support
  for setting up the database engine before they are run.  Any program
  that is able to access the disk is able to use an SQLite database.
  
  On the other hand, a database engine that uses a server can provide
  better protection from bugs in the client application - stray pointers
  in a client cannot corrupt memory on the server.  And because a server
  is a single persistent process, it is able control database access with
  more precision, allowing for finer grain locking and better concurrency.
  
  Most SQL database engines are client/server based.  Of those that are
  serverless, SQLite is the only one that this author knows of that
  allows multiple applications to access the same database at the same time.


Single Database File

  An SQLite database is a single ordinary disk file that can be located
  anywhere in the directory hierarchy.  If SQLite can read
  the disk file then it can read anything in the database.  If the disk
  file and its directory are writable, then SQLite can change anything
  in the database.   Database files can easily be copied onto a USB
  memory stick or emailed for sharing.
  
  Other SQL database engines tend to store data as a large collection of
  files.  Often these files are in a standard location that only the
  database engine itself can access.  This makes the data more secure,
  but also makes it harder to access.  Some SQL database engines provide
  the option of writing directly to disk and bypassing the filesystem
  altogether.  This provides added performance, but at the cost of
  considerable setup and maintenance complexity.


Stable Cross-Platform Database File

  The SQLite file format is cross-platform.  A database file written
  on one machine can be copied to and used on a different machine with
  a different architecture.  Big-endian or little-endian, 32-bit or
  64-bit does not matter.  All machines use the same file format.
  Furthermore, the developers have pledged to keep the file format
  stable and backwards compatible, so newer versions of SQLite can
  read and write older database files.
  
  Most other SQL database engines require you to dump and restore
  the database when moving from one platform to another and often
  when upgrading to a newer version of the software.


Compact

  When optimized for size, the whole SQLite library with everything enabled
  is less than 500KiB in size
  (as measured on an ix86 using the "size"
  utility from the GNU compiler suite.)  Unneeded features can be disabled
  at compile-time to further reduce the size of the library to under
  300KiB if desired.
  
  Most other SQL database engines are much larger than this.  IBM boasts
  that its recently released CloudScape database engine is "only" a 2MiB
  jar file - an order of magnitude larger than SQLite even after it is
  compressed!
  Firebird boasts that its client-side library is only 350KiB.  That's
  as big as SQLite and does not even contain the database engine.
  The Berkeley DB library from Oracle is 450KiB and it omits SQL
  support, providing the programmer with only simple key/value pairs.


Manifest typing

  Most SQL database engines use static typing.  A datatype is associated
  with each column in a table and only values of that particular datatype
  are allowed to be stored in that column.  SQLite relaxes this restriction
  by using manifest typing.
  In manifest typing, the datatype is a property of the value itself, not 
  of the column in which the value is stored.
  SQLite thus allows the user to store
  any value of any datatype into any column regardless of the declared type
  of that column.  (There are some exceptions to this rule: An INTEGER
  PRIMARY KEY column may only store integers.  And SQLite attempts to coerce
  values into the declared datatype of the column when it can.)
  
  As far as we can tell, the SQL language specification allows the use
  of manifest typing.   Nevertheless, most other SQL database engines are
  statically typed and so some people
  feel that the use of manifest typing is a bug in SQLite.  But the authors
  of SQLite feel very strongly that this is a feature.  The use of manifest
  typing in SQLite is a deliberate design decision which has proven in practice
  to make SQLite more reliable and easier to use, especially when used in
  combination with dynamically typed programming languages such as Tcl and
  Python.


Variable-length records

  Most other SQL database engines allocated a fixed amount of disk space
  for each row in most tables.  They play special tricks for handling
  BLOBs and CLOBs which can be of wildly varying length.  But for most
  tables, if you declare a column to be a VARCHAR(100) then the database
  engine will allocate
  100 bytes of disk space regardless of how much information you actually
  store in that column.
  
  SQLite, in contrast, use only the amount of disk space actually
  needed to store the information in a row.  If you store a single
  character in a VARCHAR(100) column, then only a single byte of disk
  space is consumed.  (Actually two bytes - there is some overhead at
  the beginning of each column to record its datatype and length.)
  
  The use of variable-length records by SQLite has a number of advantages.
  It results in smaller database files, obviously.  It also makes the
  database run faster, since there is less information to move to and from
  disk.  And, the use of variable-length records makes it possible for
  SQLite to employ manifest typing instead of static typing.


Readable source code

  The source code to SQLite is designed to be readable and accessible to
  the average programmer.  All procedures and data structures and many
  automatic variables are carefully commented with useful information about
  what they do.  Boilerplate commenting is omitted.


SQL statements compile into virtual machine code

  Every SQL database engine compiles each SQL statement into some kind of
  internal data structure which is then used to carry out the work of the
  statement.  But in most SQL engines that internal data structure is a
  complex web of interlinked structures and objects.  In SQLite, the compiled
  form of statements is a short program in a machine-language like
  representation.  Users of the database can view this 
  virtual machine language
  by prepending the EXPLAIN keyword
  to a query.
  
  The use of a virtual machine in SQLite has been a great benefit to the
  library's development.  The virtual machine provides a crisp, well-defined
  junction between the front-end of SQLite (the part that parses SQL
  statements and generates virtual machine code) and the back-end (the
  part that executes the virtual machine code and computes a result.)
  The virtual machine allows the developers to see clearly and in an
  easily readable form what SQLite is trying to do with each statement
  it compiles, which is a tremendous help in debugging.
  Depending on how it is compiled, SQLite also has the capability of
  tracing the execution of the virtual machine - printing each
  virtual machine instruction and its result as it executes.


Public domain

  The source code for SQLite is in the public domain.  No claim of copyright
  is made on any part of the core source code.  (The documentation and test
  code is a different matter - some sections of documentation and test logic
  are governed by open-source licenses.)  All contributors to the
  SQLite core software have signed affidavits specifically disavowing any
  copyright interest in the code.  This means that anybody is able to legally
  do anything they want with the SQLite source code.
  
  There are other SQL database engines with liberal licenses that allow
  the code to be broadly and freely used.  But those other engines are
  still governed by copyright law.  SQLite is different in that copyright
  law simply does not apply.  
  
  The source code files for other SQL database engines typically begin
  with a comment describing your legal rights to view and copy that file.
  The SQLite source code contains no license since it is not governed by
  copyright.  Instead of a license, the SQLite source code offers a blessing:
  
  May you do good and not evil
  May you find forgiveness for yourself and forgive others
  May you share freely, never taking more than you give.
  


SQL language extensions

  SQLite provides a number of enhancements to the SQL language 
  not normally found in other database engines.
  The EXPLAIN keyword and manifest typing have already been mentioned
  above.  SQLite also provides statements such as 
  REPLACE and the
  ON CONFLICT clause that allow for
  added control over the resolution of constraint conflicts.
  SQLite supports ATTACH and
  DETACH commands that allow multiple
  independent databases to be used together in the same query.
  And SQLite defines APIs which allow the user to add new
  SQL functions
  and collating sequences.


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


c2: Many Small Queries Are Efficient In SQLite
c5: np1queryprob.html
c4:
1. Executive Summary



200 SQL statements per webpage is excessive for client/server database
engines like MySQL, PostgreSQL, or SQL Server.


But with SQLite, 200 or more SQL statement per webpage is not a problem.


SQLite can also do large and complex queries efficiently, just like
client/server databases.  But SQLite can do many smaller queries
efficiently too.  Application developers can use whichever technique
works best for the task at hand.
     


2. The Perceived Problem


The Appropriate Uses For SQLite page says that
dynamic pages on the SQLite website typically do about 200 SQL
statements each.
This has provoked criticism from readers.  Examples:



"200 SQL statements is a ridiculously high number for a single page"

"For most sites, 200 queries is way, way, way too much."

"&#91;This is&#93; bad design"



Such criticism would be well-founded for a traditional client/server
database engine, such as MySQL, PostgreSQL, or SQL Server.  In
a client/server database, each SQL statement requires a message
round-trip from the application to the database server and back to
the application.  Doing over 200 round-trip messages, sequentially,
can be a serious performance drag.  This is sometimes called the
"N+1 Query Problem" or the "N+1 Select Problem" and it is an anti-pattern.

3. N+1 Queries Are Not A Problem With SQLite


SQLite is not client/server, however.  The SQLite database runs
in the same process address space as the application.  Queries do not
involve message round-trips, only a function call.  The latency
of a single SQL query is far less in SQLite.  Hence, using a large number
of queries with SQLite is not the problem.

4. The Need For Over 200 SQL Statements Per Webpage


The dynamic webpages on the SQLite website are mostly generated by
the Fossil version control system.
A typical dynamic
page would be a timeline such as https://www.sqlite.org/src/timeline.
A log of all SQL used by the timeline is shown below.


The first group of queries in the log are extracting display options
from the "config" and "global_config" tables of the Fossil database.
Then there is a single complex query that extracts a list of all elements
to be displayed on the timeline.
This "timeline" query demonstrates that SQLite can easily process complex
relational database queries involving multiple tables, subqueries, and
complex WHERE clause constraints, and it can make effective use of indexes
to solve the queries with minimal disk I/O.


Following the single big "timeline" query, 
there are additional queries for each timeline element.
Fossil is using the "N+1 Query" pattern rather than trying
to grab all the information in as few queries as possible.
But that is ok because there is no unnecessary IPC overhead.
At the bottom of
each timeline page, Fossil shows approximately how long it took to generate
the page.  For a 50-entry timeline, the latency is usually less than
25 milliseconds.  Profiling shows that few of those milliseconds
were spent inside the database engine.


Using the N+1 Query pattern in Fossil does not harm the application.  
But the N+1 Query pattern does have benefits.  For one, the
section of the code that creates the timeline query can be
completely separate from the section that prepares each timeline
entry for display.
This provides a separation of responsibility that helps keep the code
simple and easy to maintain.  Secondly, the information
needed for display, and the queries needed to extract that information,
vary according to what type of objects to be shown.  Check-ins need one
set of queries.  Tickets need another set of queries.  Wiki pages need a
different query.  And so forth.  By implementing these queries on-demand
and in the part of the code dealing with the various entities, there is
further separation of responsibility and simplification of the overall 
code base.


So, SQLite is able to do one or two large and complex queries, or it can
do many smaller and simpler queries.  Both are efficient.  An application
can use either or both techniques, depending on what works best for the
situation at hand.


The following is a log of all SQL used to generate one particular
timeline (captured on 2016-09-16):

-- sqlite3_open: /home/drh/sqlite/sqlite/.fslckout
PRAGMA foreign_keys=OFF;
SELECT sql FROM localdb.sqlite_schema WHERE name=='vfile';
-- sqlite3_open: /home/drh/.fossil
PRAGMA foreign_keys=OFF;
SELECT value FROM vvar WHERE name='repository';
ATTACH DATABASE '/home/drh/www/repos/sqlite.fossil' AS 'repository' KEY '';
SELECT value FROM config WHERE name='allow-symlinks';
SELECT value FROM global_config WHERE name='allow-symlinks';
SELECT value FROM config WHERE name='aux-schema';
SELECT 1 FROM config WHERE name='baseurl:http://';
SELECT value FROM config WHERE name='ip-prefix-terms';
SELECT value FROM global_config WHERE name='ip-prefix-terms';
SELECT value FROM config WHERE name='localauth';
SELECT value FROM vvar WHERE name='default-user';
SELECT uid FROM user WHERE cap LIKE '%s%';
SELECT login FROM user WHERE uid=1;
SELECT cap FROM user WHERE login = 'nobody';
SELECT cap FROM user WHERE login = 'anonymous';
SELECT value FROM config WHERE name='public-pages';
SELECT value FROM global_config WHERE name='public-pages';
SELECT value FROM config WHERE name='header';
SELECT value FROM config WHERE name='project-name';
SELECT value FROM config WHERE name='th1-setup';
SELECT value FROM global_config WHERE name='th1-setup';
SELECT value FROM config WHERE name='redirect-to-https';
SELECT value FROM global_config WHERE name='redirect-to-https';
SELECT value FROM config WHERE name='index-page';
SELECT mtime FROM config WHERE name='css';
SELECT mtime FROM config WHERE name='logo-image';
SELECT mtime FROM config WHERE name='background-image';
CREATE TEMP TABLE IF NOT EXISTS timeline(
  rid INTEGER PRIMARY KEY,
  uuid TEXT,
  timestamp TEXT,
  comment TEXT,
  user TEXT,
  isleaf BOOLEAN,
  bgcolor TEXT,
  etype TEXT,
  taglist TEXT,
  tagid INTEGER,
  short TEXT,
  sortby REAL
)
;
INSERT OR IGNORE INTO timeline SELECT
  blob.rid AS blobRid,
  uuid AS uuid,
  datetime(event.mtime,toLocal()) 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&gt;0) AS tags,
  tagid AS tagid,
  brief AS brief,
  event.mtime AS mtime
 FROM event CROSS JOIN blob
WHERE blob.rid=event.objid
 AND NOT EXISTS(SELECT 1 FROM tagxref WHERE tagid=5 AND tagtype&gt;0 AND rid=blob.rid)
 ORDER BY event.mtime DESC LIMIT 50;
-- SELECT value FROM config WHERE name='timeline-utc';
SELECT count(*) FROM timeline WHERE etype!='div';
SELECT min(timestamp) FROM timeline;
SELECT julianday('2016-09-15 14:54:51',fromLocal());
SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob WHERE blob.rid=event.objid AND mtime&lt;=2457647.121412037);
SELECT max(timestamp) FROM timeline;
SELECT julianday('2016-09-24 17:42:43',fromLocal());
SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob WHERE blob.rid=event.objid AND mtime&gt;=2457656.238009259);
SELECT value FROM config WHERE name='search-ci';
SELECT value FROM vvar WHERE name='checkout';
SELECT value FROM config WHERE name='timeline-max-comment';
SELECT value FROM global_config WHERE name='timeline-max-comment';
SELECT value FROM config WHERE name='timeline-date-format';
SELECT value FROM config WHERE name='timeline-truncate-at-blank';
SELECT value FROM global_config WHERE name='timeline-truncate-at-blank';
SELECT * FROM timeline ORDER BY sortby DESC;
SELECT value FROM config WHERE name='hash-digits';
SELECT value FROM global_config WHERE name='hash-digits';
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=68028;
SELECT pid FROM plink WHERE cid=68028 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM tagxref WHERE rid=68028 AND tagid=9 AND tagtype&gt;0;
SELECT value FROM config WHERE name='timeline-block-markup';
SELECT value FROM config WHERE name='timeline-plaintext';
SELECT value FROM config WHERE name='wiki-use-html';
SELECT value FROM global_config WHERE name='wiki-use-html';
SELECT 1 FROM private WHERE rid=68028;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=68026;
SELECT pid FROM plink WHERE cid=68026 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=68026;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=68024;
SELECT pid FROM plink WHERE cid=68024 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=68024;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=68018;
SELECT pid FROM plink WHERE cid=68018 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=68018;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=68012;
SELECT pid FROM plink WHERE cid=68012 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=68012;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=68011;
SELECT value FROM config WHERE name='details';
SELECT pid FROM plink WHERE cid=68011 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM tagxref WHERE rid=68011 AND tagid=9 AND tagtype&gt;0;
SELECT 1 FROM private WHERE rid=68011;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=68008;
SELECT pid FROM plink WHERE cid=68008 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=68008;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=68006;
SELECT pid FROM plink WHERE cid=68006 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=68006;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=68000;
SELECT pid FROM plink WHERE cid=68000 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=68000;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67997;
SELECT pid FROM plink WHERE cid=67997 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67997;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67992;
SELECT pid FROM plink WHERE cid=67992 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67992;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67990;
SELECT pid FROM plink WHERE cid=67990 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67990;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67989;
SELECT pid FROM plink WHERE cid=67989 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67989;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67984;
SELECT pid FROM plink WHERE cid=67984 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67984;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67983;
SELECT pid FROM plink WHERE cid=67983 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67983;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67979;
SELECT pid FROM plink WHERE cid=67979 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67979;
SELECT value FROM config WHERE name='ticket-closed-expr';
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='1ec41379c9c1e400' AND tkt_uuid&lt;'1ec41379c9c1e401';
SELECT 1 FROM private WHERE rid=67980;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67977;
SELECT pid FROM plink WHERE cid=67977 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='1ec41379c9c1e400' AND tkt_uuid&lt;'1ec41379c9c1e401';
SELECT 1 FROM private WHERE rid=67977;
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='1ec41379c9c1e400' AND tkt_uuid&lt;'1ec41379c9c1e401';
SELECT 1 FROM private WHERE rid=67974;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67971;
SELECT pid FROM plink WHERE cid=67971 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67971;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67972;
SELECT pid FROM plink WHERE cid=67972 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67972;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67969;
SELECT pid FROM plink WHERE cid=67969 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67969;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67966;
SELECT pid FROM plink WHERE cid=67966 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67966;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67962;
SELECT pid FROM plink WHERE cid=67962 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67962;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67960;
SELECT pid FROM plink WHERE cid=67960 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67960;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67957;
SELECT pid FROM plink WHERE cid=67957 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67957;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67955;
SELECT pid FROM plink WHERE cid=67955 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67955;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67953;
SELECT pid FROM plink WHERE cid=67953 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='5990a1bdb4a073' AND tkt_uuid&lt;'5990a1bdb4a074';
SELECT 1 FROM blob WHERE uuid&gt;='5990a1bdb4a073' AND uuid&lt;'5990a1bdb4a074';
SELECT 1 FROM private WHERE rid=67953;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67941;
SELECT pid FROM plink WHERE cid=67941 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67941;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67940;
SELECT pid FROM plink WHERE cid=67940 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67940;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67938;
SELECT pid FROM plink WHERE cid=67938 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67938;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67935;
SELECT pid FROM plink WHERE cid=67935 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67935;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67934;
SELECT pid FROM plink WHERE cid=67934 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67934;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67932;
SELECT pid FROM plink WHERE cid=67932 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67932;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67930;
SELECT pid FROM plink WHERE cid=67930 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67930;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67928;
SELECT pid FROM plink WHERE cid=67928 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM tagxref WHERE rid=67928 AND tagid=9 AND tagtype&gt;0;
SELECT 1 FROM private WHERE rid=67928;
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='0eab1ac7591f511d' AND tkt_uuid&lt;'0eab1ac7591f511e';
SELECT 1 FROM private WHERE rid=67919;
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='01874d252ac44861' AND tkt_uuid&lt;'01874d252ac44862';
SELECT 1 FROM blob WHERE uuid&gt;='01874d252ac44861' AND uuid&lt;'01874d252ac44862';
SELECT 1 FROM private WHERE rid=67918;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67916;
SELECT pid FROM plink WHERE cid=67916 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='0eab1ac759' AND tkt_uuid&lt;'0eab1ac75:';
SELECT 1 FROM private WHERE rid=67916;
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='a49bc0a8244feb08' AND tkt_uuid&lt;'a49bc0a8244feb09';
SELECT 1 FROM blob WHERE uuid&gt;='a49bc0a8244feb08' AND uuid&lt;'a49bc0a8244feb09';
SELECT 1 FROM private WHERE rid=67914;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67913;
SELECT pid FROM plink WHERE cid=67913 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='0eab1ac7591f' AND tkt_uuid&lt;'0eab1ac7591g';
SELECT 1 FROM private WHERE rid=67913;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67911;
SELECT pid FROM plink WHERE cid=67911 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67911;
SELECT status='Closed' OR status='Fixed' FROM ticket  WHERE tkt_uuid&gt;='0eab1ac7591f511d' AND tkt_uuid&lt;'0eab1ac7591f511e';
SELECT 1 FROM private WHERE rid=67909;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67907;
SELECT pid FROM plink WHERE cid=67907 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67907;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67899;
SELECT pid FROM plink WHERE cid=67899 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67899;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67897;
SELECT pid FROM plink WHERE cid=67897 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67897;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67895;
SELECT pid FROM plink WHERE cid=67895 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67895;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67893;
SELECT pid FROM plink WHERE cid=67893 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67893;
SELECT value FROM tagxref WHERE tagid=8 AND tagtype&gt;0 AND rid=67891;
SELECT pid FROM plink WHERE cid=67891 AND pid NOT IN phantom ORDER BY isprim DESC;
SELECT 1 FROM private WHERE rid=67891;
SELECT count(*) FROM plink
 WHERE pid=67928 AND isprim
   AND coalesce((SELECT value FROM tagxref
                  WHERE tagid=8 AND rid=plink.pid), 'trunk')
      =coalesce((SELECT value FROM tagxref
                  WHERE tagid=8 AND rid=plink.cid), 'trunk')
;
SELECT count(*) FROM plink
 WHERE pid=68011 AND isprim
   AND coalesce((SELECT value FROM tagxref
                  WHERE tagid=8 AND rid=plink.pid), 'trunk')
      =coalesce((SELECT value FROM tagxref
                  WHERE tagid=8 AND rid=plink.cid), 'trunk')
;
SELECT count(*) FROM plink
 WHERE pid=68028 AND isprim
   AND coalesce((SELECT value FROM tagxref
                  WHERE tagid=8 AND rid=plink.pid), 'trunk')
      =coalesce((SELECT value FROM tagxref
                  WHERE tagid=8 AND rid=plink.cid), 'trunk')
;
SELECT value FROM config WHERE name='show-version-diffs';
SELECT value FROM config WHERE name='adunit-omit-if-admin';
SELECT value FROM global_config WHERE name='adunit-omit-if-admin';
SELECT value FROM config WHERE name='adunit-omit-if-user';
SELECT value FROM global_config WHERE name='adunit-omit-if-user';
SELECT value FROM config WHERE name='adunit';
SELECT value FROM global_config WHERE name='adunit';
SELECT value FROM config WHERE name='auto-hyperlink-delay';
SELECT value FROM global_config WHERE name='auto-hyperlink-delay';
SELECT value FROM config WHERE name='footer';
PRAGMA database_list;
PRAGMA database_list;
PRAGMA localdb.freelist_count;
PRAGMA localdb.page_count;

This page last modified on  2020-06-18 21:18:56 UTC


c2: Implementation Limits For SQLite
c5: limits.html
c4:
Limits In SQLite


"Limits" in the context of this article means sizes or
quantities that can not be exceeded.  We are concerned
with things like the maximum number of bytes in a
BLOB or the maximum number of columns in a table.



SQLite was originally designed with a policy of avoiding
arbitrary limits.
Of course, every program that runs on a machine with finite
memory and disk space has limits of some kind.  But in SQLite, 
those limits
were not well defined.  The policy was that if it would fit
in memory and you could count it with a 32-bit integer, then
it should work.



Unfortunately, the no-limits policy has been shown to create
problems.  Because the upper bounds were not well
defined, they were not tested, and bugs were often found
when pushing SQLite to extremes.  For this reason, versions
of SQLite since about release 3.5.8 (2008-04-16)
have well-defined limits, and those limits are tested as part of
the test suite.



This article defines what the limits of SQLite are and how they
can be customized for specific applications.  The default settings
for limits are normally quite large and adequate for almost every
application.  Some applications may want to increase a limit here
or there, but we expect such needs to be rare.  More commonly,
an application might want to recompile SQLite with much lower
limits to avoid excess resource utilization in the event of
bug in higher-level SQL statement generators or to help thwart 
attackers who inject malicious SQL statements.



Some limits can be changed at run-time on a per-connection basis
using the sqlite3_limit() interface with one of the
limit categories defined for that interface.
Run-time limits are designed for applications that have multiple
databases, some of which are for internal use only and others which
can be influenced or controlled by potentially hostile external agents.
For example, a web browser application might use an internal database
to track historical page views but have one or more separate databases
that are created and controlled by javascript applications that are
downloaded from the internet.
The sqlite3_limit() interface allows internal databases managed by
trusted code to be unconstrained while simultaneously  placing tight
limitations on databases created or controlled by untrusted external
code in order to help prevent a denial of service attack.





Maximum length of a string or BLOB


The maximum number of bytes in a string or BLOB in SQLite is defined
by the preprocessor macro SQLITE_MAX_LENGTH.  The default value
of this macro is 1 billion (1 thousand million or 1,000,000,000).
You can raise or lower this value at compile-time using a command-line 
option like this:


-DSQLITE_MAX_LENGTH=123456789


The current implementation will only support a string or BLOB
length up to 231-1 or 2147483647.  And
some built-in functions such as hex() might fail well before that
point.  In security-sensitive applications it is best not to
try to increase the maximum string and blob length.  In fact,
you might do well to lower the maximum string and blob length
to something more in the range of a few million if that is
possible.



During part of SQLite's INSERT and SELECT processing, the complete
content of each row in the database is encoded as a single BLOB.
So the SQLITE_MAX_LENGTH parameter also determines the maximum
number of bytes in a row.



The maximum string or BLOB length can be lowered at run-time using
the sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size) interface.


Maximum Number Of Columns


The SQLITE_MAX_COLUMN compile-time parameter is used to set an upper
bound on:



The number of columns in a table
The number of columns in an index
The number of columns in a view
The number of terms in the SET clause of an UPDATE statement
The number of columns in the result set of a SELECT statement
The number of terms in a GROUP BY or ORDER BY clause
The number of values in an INSERT statement



The default setting for SQLITE_MAX_COLUMN is 2000.  You can change it
at compile time to values as large as 32767. On the other hand, many
experienced database designers will argue that a well-normalized database
will never need more than 100 columns in a table.



In most applications, the number of columns is small - a few dozen.
There are places in the SQLite code generator that use algorithms
that are O(N&sup2;) where N is the number of columns.  
So if you redefine SQLITE_MAX_COLUMN to be a
really huge number and you generate SQL that uses a large number of
columns, you may find that sqlite3_prepare_v2()
runs slowly.



The maximum number of columns can be lowered at run-time using
the sqlite3_limit(db,SQLITE_LIMIT_COLUMN,size) interface.



Maximum Length Of An SQL Statement


The maximum number of bytes in the text of an SQL statement is 
limited to SQLITE_MAX_SQL_LENGTH which defaults to 1,000,000,000.



If an SQL statement is limited to be a million bytes in length, then
obviously you will not be able to insert multi-million byte strings
by embedding them as literals inside of INSERT statements.  But
you should not do that anyway.  Use host parameters 
for your data.  Prepare short SQL statements like this:



INSERT INTO tab1 VALUES(?,?,?);



Then use the sqlite3_bind_XXXX() functions
to bind your large string values to the SQL statement.  The use of binding
obviates the need to escape quote characters in the string, reducing the
risk of SQL injection attacks.  It also runs faster since the large
string does not need to be parsed or copied as much.



The maximum length of an SQL statement can be lowered at run-time using
the sqlite3_limit(db,SQLITE_LIMIT_SQL_LENGTH,size) interface.

Maximum Number Of Tables In A Join


SQLite does not support joins containing more than 64 tables.
This limit arises from the fact that the SQLite code generator
uses bitmaps with one bit per join-table in the query optimizer.



SQLite uses an efficient query planner algorithm
and so even a large join can be prepared quickly.
Hence, there is no mechanism to raise or lower the limit on the
number of tables in a join.


Maximum Depth Of An Expression Tree


SQLite parses expressions into a tree for processing.  During
code generation, SQLite walks this tree recursively.  The depth
of expression trees is therefore limited in order to avoid
using too much stack space.



The SQLITE_MAX_EXPR_DEPTH parameter determines the maximum expression
tree depth.  If the value is 0, then no limit is enforced.  The
current implementation has a default value of 1000.



The maximum depth of an expression tree can be lowered at run-time using
the sqlite3_limit(db,SQLITE_LIMIT_EXPR_DEPTH,size) interface if the
SQLITE_MAX_EXPR_DEPTH is initially positive.  In other words, the maximum
expression depth can be lowered at run-time if there is already a 
compile-time limit on the expression depth.  If SQLITE_MAX_EXPR_DEPTH is
set to 0 at compile time (if the depth of expressions is unlimited) then
the sqlite3_limit(db,SQLITE_LIMIT_EXPR_DEPTH,size) is a no-op.




Maximum Number Of Arguments On A Function


The SQLITE_MAX_FUNCTION_ARG parameter determines the maximum number
of parameters that can be passed to an SQL function.  The default value
of this limit is 100.  SQLite should work with functions that have 
thousands of parameters.  However, we suspect that anybody who tries
to invoke a function with more than a few parameters is really
trying to find security exploits in systems that use SQLite, 
not do useful work, 
and so for that reason we have set this parameter relatively low.

The number of arguments to a function is sometimes stored in a signed
character.  So there is a hard upper bound on SQLITE_MAX_FUNCTION_ARG
of 127.


The maximum number of arguments in a function can be lowered at run-time using
the sqlite3_limit(db,SQLITE_LIMIT_FUNCTION_ARG,size) interface.


Maximum Number Of Terms In A Compound SELECT Statement


A compound SELECT statement is two or more SELECT statements connected
by operators UNION, UNION ALL, EXCEPT, or INTERSECT.  We call each
individual SELECT statement within a compound SELECT a "term".



The code generator in SQLite processes compound SELECT statements using
a recursive algorithm.  In order to limit the size of the stack, we
therefore limit the number of terms in a compound SELECT.  The maximum
number of terms is SQLITE_MAX_COMPOUND_SELECT which defaults to 500.
We think this is a generous allotment since in practice we almost
never see the number of terms in a compound select exceed single digits.



The maximum number of compound SELECT terms can be lowered at run-time using
the sqlite3_limit(db,SQLITE_LIMIT_COMPOUND_SELECT,size) interface.




Maximum Length Of A LIKE Or GLOB Pattern


The pattern matching algorithm used in the default LIKE and GLOB
implementation of SQLite can exhibit O(N&sup2;) performance (where
N is the number of characters in the pattern) for certain pathological
cases.  To avoid denial-of-service attacks from miscreants who are able
to specify their own LIKE or GLOB patterns, the length of the LIKE
or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
The default value of this limit is 50000.  A modern workstation can
evaluate even a pathological LIKE or GLOB pattern of 50000 bytes
relatively quickly.  The denial of service problem only comes into
play when the pattern length gets into millions of bytes.  Nevertheless,
since most useful LIKE or GLOB patterns are at most a few dozen bytes
in length, paranoid application developers may want to reduce this
parameter to something in the range of a few hundred if they know that
external users are able to generate arbitrary patterns.



The maximum length of a LIKE or GLOB pattern can be lowered at run-time using
the sqlite3_limit(db,SQLITE_LIMIT_LIKE_PATTERN_LENGTH,size) interface.


Maximum Number Of Host Parameters In A Single SQL Statement


A host parameter is a place-holder in an SQL statement that is filled
in using one of the
sqlite3_bind_XXXX() interfaces.
Many SQL programmers are familiar with using a question mark ("?") as a
host parameter.  SQLite also supports named host parameters prefaced
by ":", "$", or "@" and numbered host parameters of the form "?123".



Each host parameter in an SQLite statement is assigned a number.  The
numbers normally begin with 1 and increase by one with each new
parameter.  However, when the "?123" form is used, the host parameter
number is the number that follows the question mark.



SQLite allocates space to hold all host parameters between 1 and the
largest host parameter number used.  Hence, an SQL statement that contains
a host parameter like ?1000000000 would require gigabytes of storage.
This could easily overwhelm the resources of the host machine.
To prevent excessive memory allocations, 
the maximum value of a host parameter number is SQLITE_MAX_VARIABLE_NUMBER,
which defaults to 999 for SQLite versions prior to 3.32.0 (2020-05-22)
or 32766 for SQLite versions after 3.32.0.



The maximum host parameter number can be lowered at run-time using
the sqlite3_limit(db,SQLITE_LIMIT_VARIABLE_NUMBER,size) interface.


Maximum Depth Of Trigger Recursion


SQLite limits the depth of recursion of triggers in order to prevent
a statement involving recursive triggers from using an unbounded amount
of memory.  


Prior to SQLite version 3.6.18 (2009-09-11), 
triggers were not recursive and so
this limit was meaningless.  Beginning with version 3.6.18, recursive triggers
were supported but had to be explicitly enabled using the
PRAGMA recursive_triggers statement.  
Beginning with version 3.7.0 (2009-09-11), 
recursive triggers are enabled by default but can be manually disabled
using PRAGMA recursive_triggers.  The SQLITE_MAX_TRIGGER_DEPTH is
only meaningful if recursive triggers are enabled.

The default maximum trigger recursion depth is 1000.

Maximum Number Of Attached Databases


The ATTACH statement is an SQLite extension
that allows two or more databases to be associated to the same database
connection and to operate as if they were a single database.  The number
of simultaneously attached databases is limited to SQLITE_MAX_ATTACHED
which is set to 10 by default.
The maximum number of attached databases cannot be increased above 125.


The maximum number of attached databases can be lowered at run-time using
the sqlite3_limit(db,SQLITE_LIMIT_ATTACHED,size) interface.


Maximum Number Of Pages In A Database File


SQLite is able to limit the size of a database file to prevent
the database file from growing too large and consuming too much
disk space.
The SQLITE_MAX_PAGE_COUNT parameter, which is normally set to
1073741823, is the maximum number of pages allowed in a single
database file.  An attempt to insert new data that would cause
the database file to grow larger than this will return
SQLITE_FULL.



The largest possible setting for SQLITE_MAX_PAGE_COUNT is 4294967294.
When used with the maximum page size of 65536, this gives a maximum
SQLite database size of about 281 terabytes.


The 
max_page_count PRAGMA can be used to raise or lower this
limit at run-time.

Maximum Number Of Rows In A Table


The theoretical maximum number of rows in a table is
264 (18446744073709551616 or about 1.8e+19).
This limit is unreachable since the maximum database size of 281 terabytes
will be reached first.  A 281 terabytes database can hold no more than
approximately 2e+13 rows, and then only if there are no indices and if
each row contains very little data.
Maximum Database Size


Every database consists of one or more "pages".  Within a single database,
every page is the same size, but different databases can have page sizes
that are powers of two between 512 and 65536, inclusive.  The maximum
size of a database file is 4294967294 pages.  At the maximum page size
of 65536 bytes, this translates into a maximum database size of 
approximately 1.4e+14 bytes (281 terabytes, or 256 tebibytes, or
281474 gigabytes or 256,000 gibibytes).

This particular upper bound is untested since the developers do not 
have access to hardware capable of reaching this limit.  However, tests
do verify that SQLite behaves correctly and sanely when a database 
reaches the maximum file size of the underlying filesystem (which is
usually much less than the maximum theoretical database size) and when
a database is unable to grow due to disk space exhaustion.
Maximum Number Of Tables In A Schema


Each table and index requires at least one page in the database file.
An "index" in the previous sentence means an index created explicitly
using a CREATE INDEX statement or implicit indices created by UNIQUE
and PRIMARY KEY constraints.  Since the maximum number of pages in a
database file is 2147483646 (a little over 2 billion) this is also then
an upper bound on the number of tables and indices in a schema.

Whenever a database is opened, the entire schema is scanned and parsed
and a parse tree for the schema is held in memory.  That means that
database connection startup time and initial memory usage
is proportional to the size of the schema.


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


c2: Constraint Conflict Resolution in SQLite
c5: conflict.html
c4:
Constraint Conflict Resolution in SQLite


In most SQL databases, if you have a UNIQUE, NOT NULL, or
CHECK constraint on
a table and you try to do an UPDATE or INSERT that violates
the constraint, the database will abort the operation in
progress, back out any prior changes associated with the same
UPDATE or INSERT statement, and return an error.
This is the default behavior of SQLite, though SQLite also allows one to
define alternative ways for dealing with constraint violations.
This article describes those alternatives and how to use them.


Conflict Resolution Algorithms


SQLite defines five constraint conflict resolution algorithms
as follows:



ROLLBACK
When a constraint violation occurs, an immediate ROLLBACK
occurs, thus ending the current transaction, and the command aborts
with a return code of SQLITE_CONSTRAINT.  If no transaction is
active (other than the implied transaction that is created on every
command) then this algorithm works the same as ABORT.

ABORT
When a constraint violation occurs, the command backs out
any prior changes it might have made and aborts with a return code
of SQLITE_CONSTRAINT.  But no ROLLBACK is executed so changes
from prior commands within the same transaction
are preserved.  This is the default behavior for SQLite.

FAIL
When a constraint violation occurs, the command aborts with a
return code SQLITE_CONSTRAINT.  But any changes to the database that
the command made prior to encountering the constraint violation
are preserved and are not backed out.  For example, if an UPDATE
statement encountered a constraint violation on the 100th row that
it attempts to update, then the first 99 row changes are preserved
but change to rows 100 and beyond never occur.

IGNORE
When a constraint violation occurs, the one row that contains
the constraint violation is not inserted or changed.  But the command
continues executing normally.  Other rows before and after the row that
contained the constraint violation continue to be inserted or updated
normally.  No error is returned.

REPLACE
When a UNIQUE constraint violation occurs, the pre-existing row
that caused the constraint violation is removed prior to inserting
or updating the current row.  Thus the insert or update always occurs.
The command continues executing normally.  No error is returned.

This page last modified on  2014-08-15 14:59:54 UTC


c2: Custom Builds Of SQLite
c5: custombuild.html
c4:
Custom Builds Of SQLite
or
Porting SQLite To New Operating Systems


1.0 Introduction

For most applications, the recommended method for building
SQLite is to use the amalgamation code
file, sqlite3.c, and its corresponding header file
sqlite3.h.  The sqlite3.c code file should compile and
run on any Unix, Windows system without any changes
or special compiler options.  Most applications can simply include
the sqlite3.c file together with the other C code files that make
up the application, compile them all together, and have working
and well configured version of SQLite.

Most applications work great with SQLite in its
default configuration and with no special compile-time configuration.
Most developers should be able to completely ignore this document
and simply build SQLite from
the amalgamation without any
special knowledge and without taking any special actions.

However, highly tuned and specialized
applications may want or need to replace some of
SQLite's built-in system interfaces with alternative implementations
more suitable for the needs of the application.  SQLite is designed
to be easily reconfigured at compile-time to meet the specific
needs of individual projects.  Among the compile-time configuration
options for SQLite are these:


 Replace the built-in mutex subsystem with an alternative
        implementation.  

 Completely disable all mutexing for use in single-threaded
        applications. 

 Reconfigure the memory allocation subsystem to use a memory
        allocator other the malloc() implementation from the standard
        library. 

 Realign the memory allocation subsystem so that it never calls
        malloc() at all but instead satisfies all memory requests using
        a fixed-size memory buffer assigned to SQLite at startup. 

 Replace the interface to the file system with an alternative
        design.  In other words, override all of the system calls that
        SQLite makes in order to talk to the disk with a completely different
        set of system calls. 

 Override other operating system interfaces such as calls to obtain
        Zulu or local time. 


Generally speaking, there are three separate subsystems within
SQLite that can be modified or overridden at compile-time.  The
mutex subsystem is used to serialize access to SQLite resources that
are shared among threads.  The memory allocation subsystem is used
to allocate memory required by SQLite objects and for the database
cache.  Finally, the Virtual File System subsystem is
used to provide a portable interface between SQLite and the underlying
operating system and especially the file system.  We call these three
subsystems the "interface" subsystems of SQLite.

We emphasis that most applications are well-served by the 
built-in default implementations of the SQLite interface subsystems.
Developers are encouraged to use the
default built-in implementations whenever possible
and to build SQLite without any special compile-time options or parameters.
However, some highly specialized applications may benefit from
substituting or modifying one or more of these built-in SQLite
interface subsystems.
Or, if SQLite is used on an operating system other than
Unix (Linux or Mac OS X), Windows (Win32 or WinCE), or OS/2 then none
of the interface subsystems that come built into SQLite will work
and the application will need to provide alternative implementations
suitable for the target platform.

2.0 Configuring Or Replacing The Mutex Subsystem

In a multithreaded environment, SQLite uses mutexes to serialize
access to shared resources.
The mutex subsystem is only required for applications that access
SQLite from multiple threads.  For single-threaded applications, or
applications which only call SQLite from a single thread, the mutex
subsystem can be completely disabled by recompiling with the following
option:


-DSQLITE_THREADSAFE=0


Mutexes are cheap but they are not free, so performance will be better
when mutexes are completely disabled.  The resulting library footprint
will also be a little smaller.  Disabling the mutexes at compile-time
is a recommended optimization for applications where it makes sense.

When using SQLite as a shared library, an application can test to see
whether or not mutexes have been disabled using the
sqlite3_threadsafe() API.  Applications that link against SQLite at
run-time and use SQLite from multiple threads should probably check this
API to make sure they did not accidentally get linked against a version of
the SQLite library that has its mutexes disabled.  Single-threaded
applications will, of course, work correctly regardless of whether or
not SQLite is configured to be threadsafe, though they will be a little
bit faster when using versions of SQLite with mutexes disabled.

SQLite mutexes can also be disabled at run-time using the
sqlite3_config() interface.  To completely disable all mutexing,
the application can invoke:


sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);


Disabling mutexes at run-time is not as effective as disabling them
at compile-time since SQLite still must do a test of a boolean variable
to see if mutexes are enabled or disabled at each point where a mutex
might be required.  But there is still a performance advantage for
disabling mutexes at run-time.

For multi-threaded applications that are careful about how they
manage threads, SQLite supports an alternative run-time configuration
that is half way between not using any mutexes and the default situation
of mutexing everything in sight.  This in-the-middle mutex alignment can
be established as follows:


sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0);


There are two separate configuration changes here which can
be used either together or separately. The
SQLITE_CONFIG_MULTITHREAD setting disables the mutexes that
serialize access to database connection objects and 
prepared statement objects.  With this setting, the application
is free to use SQLite from multiple threads, but it must make sure
than no two threads try to access the same database connection
or any prepared statements associated with the same 
database connection at the same time.  Two threads can use SQLite
at the same time, but they must use separate database connections.
The second SQLITE_CONFIG_MEMSTATUS setting disables the mechanism
in SQLite that tracks the total size of all outstanding memory
allocation requests.  This omits the need to mutex each call
to sqlite3_malloc() and sqlite3_free(), which saves a huge
number of mutex operations.  But a consequence of disabling the
memory statistics mechanism is that the 
sqlite3_memory_used(), sqlite3_memory_highwater(), and
sqlite3_soft_heap_limit64() interfaces cease to work.


SQLite uses pthreads for its mutex implementation on Unix and
SQLite requires a recursive mutex.  Most modern pthread implementations
support recursive mutexes, but not all do.  For systems that do not
support recursive mutexes, it is recommended that applications operate
in single-threaded mode only.  If this is not possible, SQLite provides
an alternative recursive mutex implementation built on top of the
standard "fast" mutexes of pthreads.  This alternative
implementation should work correctly as long as pthread_equal() is
atomic and the processor has a coherent data cache.  The alternative
recursive mutex implementation is enabled by the following
compiler command-line switch:


-DSQLITE_HOMEGROWN_RECURSIVE_MUTEX=1


When porting SQLite to a new operating system, it is usually necessary
to completely replace the built-in mutex subsystem with an alternative
built around the mutex primitives of the new operating system.  This
is accomplished by compiling SQLite with the following option:


-DSQLITE_MUTEX_APPDEF=1


When SQLite is compiled with the SQLITE_MUTEX_APPDEF=1 option, it
completely omits the implementation of its 
mutex primitive functions.  But the SQLite
library still attempts to call these functions where necessary, so the
application must itself implement the
mutex primitive functions and link them together
with SQLite.

3.0 Configuring Or Replacing The Memory Allocation Subsystem

By default, SQLite obtains the memory it needs for objects and
cache from the malloc()/free() implementation of the standard library.
There is also on-going work with experimental memory allocators that
satisfy all memory requests from a single fixed memory buffer handed
to SQLite at application start.  Additional information on these
experimental memory allocators will be provided in a future revision
of this document.

SQLite supports the ability of an application to specify an alternative
memory allocator at run-time by filling in an instance of the
sqlite3_mem_methods object with pointers to the routines of the
alternative implementation then registering the new alternative
implementation using the sqlite3_config() interface.
For example:


sqlite3_config(SQLITE_CONFIG_MALLOC, &my_malloc_implementation);


SQLite makes a copy of the content of the sqlite3_mem_methods object
so the object can be modified after the sqlite3_config() call returns.

4.0 Adding New Virtual File Systems

Since version 3.5.0 (2007-09-04), 
SQLite has supported an interface called the
virtual file system or "VFS".
This object is somewhat misnamed since it
is really an interface to the whole underlying operating system, not
just the filesystem.

 One of the interesting features
of the VFS interface is that SQLite can support multiple VFSes at the
same time.  Each database connection has to choose a single VFS for its
use when the connection is first opened using sqlite3_open_v2().
But if a process contains multiple database connections each can choose
a different VFS.  VFSes can be added at run-time using the
sqlite3_vfs_register() interface.

The default builds for SQLite on Unix, Windows, and OS/2 include 
a VFS appropriate for the target platform.  SQLite builds for other
operating systems do not contain a VFS by default, but the application
can register one or more at run-time.

5.0 Porting SQLite To A New Operating System

In order to port SQLite to a new operating system - an operating
system not supported by default - the application
must provide...


 a working mutex subsystem (but only if it is multithreaded), 
 a working memory allocation subsystem (assuming it lacks malloc()
in its standard library), and
 a working VFS implementation.


All of these things can be provided in a single auxiliary C code file
and then linked with the stock "sqlite3.c" code file to generate a working
SQLite build for the target operating system.  In addition to the
alternative mutex and memory allocation subsystems and the new VFS,
the auxiliary C code file should contain implementations for the
following two routines:


 sqlite3_os_init() 
 sqlite3_os_end() 


The "sqlite3.c" code file contains default implementations of a VFS
and of the sqlite3_initialize() and sqlite3_shutdown() functions that
are appropriate for Unix, Windows, and OS/2.
To prevent one of these default components from being loaded when sqlite3.c
is compiled, it is necessary to add the following compile-time
option:


-DSQLITE_OS_OTHER=1



The SQLite core will call sqlite3_initialize() early.  The auxiliary
C code file can contain an implementation of sqlite3_initialize() that
registers an appropriate VFS and also perhaps initializes an alternative
mutex system (if mutexes are required) or does any memory allocation
subsystem initialization that is required.
The SQLite core never calls sqlite3_shutdown() but it is part of the
official SQLite API and is not otherwise provided when compiled with
-DSQLITE_OS_OTHER=1, so the auxiliary C code file should probably provide
it for completeness.
This page last modified on  2021-11-17 15:30:21 UTC


c2: SQLite Consortium Agreement
c5: consortium_agreement-20071201.html
c4:
SQLite Consortium Agreement


This SQLite Consortium Agreement ("Agreement") is made and
entered into as of the _____ day of ______________, 2007 ("Effective Date")
by and between ___________________ (the "Company"), and
Hipp, Wyrick & Company, Inc., a Georgia Corporation with
headquarters at 6200 Maple Cove Lane, Charlotte, NC ("Hwaci").

WHEREAS, Hwaci is the developer of a serverless, embeddable, public
domain SQL database engine available at 
http://www.sqlite.org/
("SQLite"); and

WHEREAS, Company wishes to support the independent development of 
the SQLite database engine to insure the continuing reliability, 
vitality, and independence of SQLite, and in connection therewith,
Company wishes to provide funds for ongoing research, development, 
and maintenance of the SQLite code base, operation of the SQLite 
website, protection and maintenance of the SQLite
trademark, as well as for promotion of SQLite at conferences and
trade shows; and

WHEREAS, Company wishes to receive benefits in the form of
services from Hwaci in consideration for their support of SQLite; and

WHEREAS, Company and Hwaci each wish SQLite to be supported and 
maintained as an independent, community-driven project, and to 
ensure the SQLite development team remains independent.

NOW, THEREFORE, in consideration of the mutual promises contained 
herein, the parties agree as follows:

1.0 Definitions

1.1 SQLite Developers
The "SQLite Developers" are the employees or contractors of Hwaci engaged 
in the development of SQLite, including without limitation the 
SQLite Architect.

1.2 SQLite Architect
The "SQLite Architect" is the SQLite Developer with ultimate 
responsibility and authority over changes and maintenance of the 
SQLite code.  The current SQLite Architect is the original designer
and developer of SQLite, D. Richard Hipp.   Hwaci may change the 
SQLite Architect from time to time upon approval by Company.

1.3 Consortium Member
A "Consortium Member" is a company or organization, including
but not limited to Company, which has entered into an agreement
with Hwaci which is substantially similar to this Agreement.


2.0 Agreement

2.1 Responsibilities And Obligations Of SQLite Developers

2.1.1 General Support
The SQLite Developers shall provide, without limit,
timely and accurate answers, advice, and instruction
in response to questions and comments from Company about SQLite
submitted by email or by telephone at any time day or night.


2.1.2 Debugging Support
The SQLite Developers shall at Company's request provide
Company with direct assistance
in debugging applications that are built upon or use SQLite.
The combined time for Debugging Support and Custom
Development for Company is limited to 330 hours per year.


2.1.3 Custom Development
The SQLite Developers shall at the request of Company
write new extensions or enhancements
to SQLite according to Company's specifications.  These extensions
and enhancements may be proprietary to Company or open source or
with the consent of both Company and the SQLite Architect may
be folded into the public domain SQLite source tree.
The time devoted to Custom Development for Company is limited 220 hours
per year.


2.1.4 Custom Builds
The SQLite Developers shall at Company's request provide Company
with specialized builds of SQLite according to Company's specifications.


2.1.5 Legacy Support
The SQLite Developers shall at Company's request provide support
and bug-fix patches for any historical version of SQLite.


2.1.6 Custom Testing
The SQLite Developers shall at Company's request set up and run
acceptance tests according Company's specifications that are specifically 
designed to exercise SQLite as configured and used by Company.
These acceptance tests shall be run and shall pass prior to any release
of SQLite.


2.1.7 Priority Bug Fixes
The SQLite Developers shall assign highest priority to fixing bugs
in SQLite that are reported by Company or in which Company has
expressed a specific interest.


2.1.8 Code Quality
The SQLite Developers shall at all times keep the SQLite source 
code well commented and documented and clearly structured and 
organized so that an experienced and competent programmer can
understand it and support it after no more than a few months of study.


2.1.9 Backwards Compatibility
The SQLite Developers recognize that Company uses SQLite 
in mission-critical applications and therefore shall work diligently 
to ensure continuing bug-free correct operation and backwards 
compatibility with prior releases.


2.1.10 Test Coverage
The SQLite Developers shall maintain the SQLite test suite such
that no less than 95% source code coverage is provided.


2.1.11 Website
The SQLite Developers shall maintain the SQLite website at
http://www.sqlite.org/
in good working order and all SQLite source code shall 
be made freely available at such website. 



2.2 Responsibilities And Obligations Of The SQLite Architect

2.2.1 Private Briefings
The SQLite Architect shall, at the request of Company, 
provide Company with private notification and briefings
of any new bugs or new features in SQLite that might 
effect Company's products.


2.2.2 Direction
The SQLite Architect shall coordinate the activities of SQLite
Developers and shall publish from time to time a roadmap of
proposed future changes and enhancements to SQLite.


2.2.3 Oversight
The SQLite Architect shall personally review all changes to 
the SQLite Source Code and take responsibility for the quality 
and correctness of those changes.


2.2.4 Continuity
The initial SQLite Architect shall be the original developer
of SQLite, D. Richard Hipp.  The role of SQLite Architect shall
not be assigned to another during the term of this Agreement except 
due to the disability of Dr. Hipp and with approval of Company.


2.3 Responsibilities And Obligations Of Hwaci

2.3.1 Employer
Hwaci shall act as the employer of the SQLite Developers and
SQLite Architect and shall make all tax and legal filings
and tax withholding required by employers.  Hwaci shall provide
Company with W-9 information upon request.


2.3.2 Responsible Party
All obligations of the SQLite Developers set forth in this
agreement are deemed obligations of Hwaci.  Hwaci shall recruit, 
employ, and supervise SQLite Developers in such a way that the
responsibilities and obligations of the SQLite Developers set 
forth in this agreement are upheld.

2.3.3 Multiple Developers
Hwaci shall recruit and employ as many SQLite Developers for as
many hours as can be reasonably achieved using the funds received 
from Consortium Members under this agreement.
So that support for SQLite will not be interrupted by the
disability or withdrawal of any one SQLite Developer, Hwaci will
keep at least two knowledgeable and competent SQLite Developers
on staff.

2.3.4 Mentorship
Hwaci shall work to encourage independent 
programmers from around the world
to become familiar with SQLite internals so that there will be a
pool of talent able to support SQLite in the future.


2.3.5 Audits
Hwaci shall keep and maintain complete and accurate records
of the use of development funds provided by Company
and shall allow Company, or its representative, a certified 
public accountant mutually acceptable to Hwaci and Company, 
during office hours and at reasonable intervals, no more than 
once every 12 months, to inspect and make extracts or copies
of such records solely for the purpose of ascertaining Hwaci's 
compliance with the objectives and requirements of this agreement.


2.3.6 Disaster Planning
Hwaci shall maintain backup copies of all
SQLite source files and documentation, current and historical,
at at least two separate locations separated from each
other and from the primary on-line SQLite repository
by at least 400 kilometers.


2.3.7 Trademark
Hwaci shall maintain ownership of the SQLite trademark and
the sqlite.org domain name and shall purchase bandwidth and
server space for the 
http://www.sqlite.org/ website.


2.3.8 No Take-overs or Buy-outs
Neither Hwaci nor the SQLite Architect shall relinquish development
control of SQLite during the term of this Agreement, by acquisition or merger 
or by any other means,
except with the consent of Company.


2.3.9 New Consortium Members
New Consortium Members may be accepted into the consortium from
time to time under identical terms as this agreement, or under
substantially similar terms that have been approved by existing
Consortium Members.

2.3.10 Adequate Staff
Hwaci shall recruit and employ a sufficient number of qualified
SQLite Developers to easily cover all custom development,
debugging, and general support service obligations for all
Consortium Members while still providing ample time for
the SQLite Developers to engage in general maintenance
and extension of SQLite.


2.3.11 Use Of Funds
Hwaci shall use the funds provided hereunder
solely for the development and maintenance of SQLite as set forth in
this Agreement.
Interest on funds received in advance and held in trust will
be reinvested and used for the same purposes as the principal.


2.4 Responsibilities And Obligations Of Company

2.4.1 Funding
Company shall provide funding for the ongoing support and
maintenance of SQLite as set forth in section 3.0 "Fees".


2.4.2 Copyright Disclaimer
Company acknowledges that SQLite source code and documentation
published on the SQLite website
is in the public domain and that nothing in this agreement shall change
that fact.


3.0 Fees

In consideration of the performance
by Hwaci, the SQLite Developers, and the SQLite Architect
of the obligations described herein,
Company shall pay Hwaci at least US $75,000 per year in advance
either annually, quarterly, or monthly, at Company's discretion.

4.0 Confidentiality

4.1 Definition of Confidential Information

"Confidential Information" means any Company proprietary information, 
technical data, trade secrets or know-how, including, but not limited to, 
research, product plans, products, services, customers, customer lists, 
markets, software, developments, inventions, processes, formulas, 
technology, designs, drawings, engineering, hardware configuration 
information, marketing, finances or other business information 
disclosed by Company either directly or indirectly in writing, 
orally or by drawings or inspection of parts or equipment.

4.2 Non-Use and Non-Disclosure.

Hwaci shall not, during or subsequent to the term of this Agreement,
use Company's Confidential Information for any purpose whatsoever
other than the performance of the Services or disclose 
Company's Confidential Information to any third party.  The parties 
acknowledge that Confidential Information will remain the sole
property of Company.  Hwaci shall take all reasonable precautions 
to prevent any unauthorized disclosure of Confidential Information 
including, but not limited to, having each employee or 
consultant of Hwaci, if any, with access to any 
Confidential Information, execute a nondisclosure agreement
containing provisions in Company's favor substantially similar 
to this Agreement.  Confidential Information does not include
information that: (i) is known to Hwaci at the time of 
disclosure to Hwaci by Company as evidenced by written 
records of Hwaci; (ii) has become publicly known and made 
generally available through no wrongful act of Hwaci; or 
(iii) has been received by Hwaci from a third party who is 
authorized to make such disclosure.

4.2.1 Disclosure Required by Law
In the event any Confidential Information is required to be disclosed 
by Hwaci under the terms of a valid and effective subpoena or order 
issued by a court of competent jurisdiction, or by a demand or 
information request from an executive or administrative agency 
or other governmental authority, Hwaci shall, unless prohibited
by the terms of a subpoena, order, or demand, promptly notify 
Company of the existence, terms and circumstances surrounding 
such demand or request, shall consult with Company on the 
advisability of taking legally available steps to resist 
or narrow such demand or request, and, if disclosure of 
such Confidential Information is required, shall exercise 
its reasonable best efforts to narrow the scope of disclosure 
and obtain an order or other reliable assurance that 
confidential treatment will be accorded to such 
Confidential Information.  To the extent that Hwaci
is prohibited from notifying Company of a subpoena, 
order or demand, by the terms of same, Hwaci shall exercise 
its reasonable efforts to narrow the scope of disclosure.

4.3 Return of Materials.

Upon the termination of this Agreement, or upon Company's 
earlier request, Hwaci shall deliver to Company all of
Company's property or Confidential Information that Hwaci 
may have in Hwaci's possession or control.

5.0 Intellectual Property

5.1 No Assignment

Company acknowledges that all copyrightable material, notes, 
records, drawings, designs, inventions, improvements, developments, 
discoveries and trade secrets made, generated, conceived, or
reduced to practice by Hwaci related to SQLite
will remain the property of Hwaci.  Nothing in this Agreement
will be construed to transfer any intellectual property right 
of Hwaci to Company.

5.2 Availability and Public Domain Dedication

The SQLite Developers and Hwaci shall, 
subject to their discretion as to the quality
and suitability of the SQLite source code and documentation
for public release, make 
the SQLite source code and documentation
publicly available as downloadable files
and make a public statement ceding all intellectual 
property rights, including but not limited to copyright
and patent rights, in the SQLite source code and documentation
to the public domain.  
To the extent that the SQLite Developers and Hwaci 
elect not to release the SQLite
source code and documentation
publicly, they shall provide copies thereof to 
Company and hereby grants to Company, under all of the 
SQLite Developers' and Hwaci's 
rights
including but not limited to copyright and patent rights,
in and to the SQLite source code and documentation, 
perpetual, irrevocable, 
worldwide, non-exclusive, sublicenseable license to use, 
copy, prepare derivative works of, publicly perform and 
display the SQLite source code and documentation 
and derivative works thereof.

5.3 Trademark

Hwaci shall use the name "SQLite" only to apply to the 
publicly available project known by such name as of the 
Effective Date.  Hwaci may in its discretion file such 
trademark applications or registrations as it deems 
appropriate to protect or record its rights therein, 
and may set such policies as it deems appropriate for 
licensing the use of the trademark.

6.0 Representations And Warranties

6.1 Intellectual Property Clearances.

Hwaci hereby represents and warrants that Hwaci shall 
enter into agreements with the SQLite Developers sufficient 
to enable Hwaci to undertake the obligations of Section 5.

6.2 Disclaimer.

THE WORK PRODUCT AND ALL MATERIAL PROVIDED BY HWACI AND 
COMPANY ARE PROVIDED "AS IS."  NEITHER PARTY MAKES ANY 
REPRESENTATIONS OR WARRANTIES OF ANY KIND, WHETHER ORAL
OR WRITTEN, WHETHER EXPRESS, IMPLIED, OR ARISING BY STATUTE, 
CUSTOM, COURSE OF DEALING OR TRADE USAGE, WITH RESPECT TO 
THE SUBJECT MATTER HEREOF, IN CONNECTION WITH THIS AGREEMENT.  
EACH PARTY SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.

7.0 Term And Termination

7.1 Term.

This Agreement will commence on the Effective Date and 
will continue until 12 months after the Effective Date.
Thereafter, the parties may by mutual consent renew 
this Agreement subject to agreement on fees to be paid by 
Company for sponsorship for additional periods.

7.2 Termination.

If either party materially defaults in the performance 
of any of its material obligations hereunder and if any 
such default is not corrected within 30 days after notice 
in writing, then the non-defaulting party, at its option, 
may, in addition to any other remedies it may have, thereupon 
terminate this Agreement by giving written notice of 
termination to the defaulting party.

7.3 Survival.

Upon such termination all rights and duties of the
parties toward each other will cease except:  
Sections 4 (Confidentiality), 5 (Intellectual Property), 
and 8 (Miscellaneous) will survive termination of this Agreement.

8. Miscellaneous

8.1 Nonassignment/Binding Agreement.

The parties acknowledge that the unique nature of 
Hwaci's services are substantial consideration for the 
parties' entering into this Agreement.  Neither this 
Agreement nor any rights under this Agreement may be 
assigned or otherwise transferred by Hwaci, in whole 
or in part, whether voluntarily or by operation of law, 
without the prior written consent of Company, which 
consent will not be unreasonably withheld.  
Subject to the foregoing, this Agreement will be binding
upon and will inure to the benefit of the parties and
their respective successors and assigns. Any assignment 
in violation of the foregoing will be null and void.

8.2 Notices.

Any notice required or permitted under the terms of 
this Agreement or required by law must be in writing 
and must be:  (a) delivered in person; (b) sent by first 
class registered mail, or air mail, as appropriate; or 
(c) sent by overnight air courier, in each case properly 
posted and fully prepaid to the appropriate address set 
forth in the preamble to this Agreement.  Either party 
may change its address for notice by notice to the other 
party given in accordance with this Section.  Notices 
will be considered to have been given at the time of
actual delivery in person, three business days after 
deposit in the mail as set forth above, or one day after 
delivery to an overnight air courier service.

8.3 Waiver.

Any waiver of the provisions of this Agreement or 
of a party's rights or remedies under this Agreement 
must be in writing to be effective.  Failure, neglect, 
or delay by a party to enforce the provisions of this 
Agreement or its rights or remedies at any time, will
not be construed as a waiver of such party's rights 
under this Agreement and will not in any way affect 
the validity of the whole or any part of this Agreement 
or prejudice such party's right to take subsequent action. 
No exercise or enforcement by either party of any right
or remedy under this Agreement will preclude the 
enforcement by such party of any other right or remedy 
under this Agreement or that such party is entitled by 
law to enforce.

8.4 Severability.

If any term, condition, or provision in this Agreement 
is found to be invalid, unlawful or unenforceable to 
any extent, the parties shall endeavor in good faith 
to agree to such amendments that will preserve, as far
as possible, the intentions expressed in this Agreement. 
If the parties fail to agree on such an amendment, 
such invalid term, condition or provision will be 
severed from the remaining terms, conditions and
provisions, which will continue to be valid and 
enforceable to the fullest extent permitted by law.

8.5 Integration.

This Agreement contains the entire agreement of the 
parties with respect to the subject matter of this 
Agreement and supersedes all previous communications, 
representations, understandings and agreements, 
either oral or written, between the parties with 
respect to said subject matter.  This Agreement 
may not be amended, except by a writing signed by both parties.

8.6 Counterparts.

This Agreement may be executed in counterparts, 
each of which so executed will be deemed to be an 
original and such counterparts together will constitute 
one and the same agreement.

8.7 Governing Law.

This Agreement will be interpreted and construed in 
accordance with the laws of the State of North Carolina
and the United States of America, without regard to
conflict of law principles.  All disputes arising out 
of this Agreement will be subject to the exclusive 
jurisdiction of the state and federal courts located in 
North Carolina, and each party hereby consents to the 
personal jurisdiction thereof.

8.8 Independent Contractors.

It is the intention of the parties that Hwaci is an 
independent contractor.  Nothing in this Agreement will 
in any way be construed to constitute Hwaci or any of 
its employees as an agent, employee or representative 
of Company.

9.0 Signatures

The parties have executed this Agreement below to 
indicate their acceptance of its terms.



HWACI
By:
&nbsp;
Print Name:
&nbsp;
Title:
&nbsp;


COMPANY
By:
&nbsp;
Print Name:
&nbsp;
Title:
&nbsp;


c2: SQLite: Single File Database
c5: onefile.html
c4:
Single-file Cross-platform Database


A database in SQLite is a single disk file&sup1;.
Furthermore, the file format is cross-platform.
A database that is created on one machine can be
copied and used on a different machine with
a different architecture.  SQLite databases
are portable across 32-bit and 64-bit machines
and between 
big-endian and 
little-endian
architectures.



The SQLite database file format is also stable.
All releases of SQLite version 3 can read and write database
files created by the very first SQLite 3 release (version 3.0.0)
going back to 2004-06-18.  This is "backwards compatibility".
The developers promise to maintain backwards compatibility of
the database file format for all future releases of SQLite 3.
"Forwards compatibility" means that older releases
of SQLite can also read and write databases created by newer
releases.  SQLite is usually, but not completely forwards
compatible. 



The stability of the SQLite database file format and the fact
that the file format is cross-platform combine to make SQLite
database files an excellent choice as an 
Application File Format.
The US Library Of Congress acknowledges this by listing SQLite
as a recommended storage format for long-term preservation of
digital content.





Notes:

Temporary journal files are created as part of transaction control,
but those extra files are not part of the steady-state database.


This page last modified on  2020-04-06 18:59:20 UTC


c2: The sqlite3_analyzer.exe Utility Program
c5: sqlanalyze.html
c4:
1. The sqlite3_analyzer.exe Utility Program


The sqlite3_analyzer.exe binary is a command-line utility program
that measures and displays how much and how efficiently space is used by 
individual tables and indexes with an SQLite database file.
Example usage:


sqlite3_analyzer database.sqlite



The output is a human-readable ASCII text report that provides information
on the space utilization of the database file.  The report is intended to
be self-explanatory, though there is some 
additional explanation of the
various parameters reported toward the end of the report.


The output is also valid SQL.  Most of the report text is contained within
a header comment, with various SQL statements that create and initialize
a database at the
end of the report.  The constructed database contains
the raw data from which the report was extracted.  Hence the original
report can be read into an instance of the command-line shell and then
the raw data can be queried to dig deeper into the space utilization of
a particular database file.

1.1. Implementation


The sqlite3_analyzer.exe program is a
TCL program that uses the dbstat virtual table
to gather information about the database file and then format that
information neatly.



1.2. Example Output

The following is sqlite3_analyzer output for an example
places.sqlite database used by Firefox.


/** Disk-Space Utilization Report For &#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;/places.sqlite

Page size in bytes................................ 32768     
Pages in the whole file (measured)................ 221       
Pages in the whole file (calculated).............. 221       
Pages that store data............................. 221        100.0% 
Pages on the freelist (per header)................ 0            0.0% 
Pages on the freelist (calculated)................ 0            0.0% 
Pages of auto-vacuum overhead..................... 0            0.0% 
Number of tables in the database.................. 14        
Number of indices................................. 23        
Number of defined indices......................... 17        
Number of implied indices......................... 6         
Size of the file in bytes......................... 7241728   
Bytes of user payload stored...................... 2503069     34.6% 

*** Page counts for all tables with their indices *****************************

MOZ_PLACES........................................ 142         64.3% 
MOZ_HISTORYVISITS................................. 41          18.6% 
MOZ_FAVICONS...................................... 15           6.8% 
MOZ_BOOKMARKS..................................... 5            2.3% 
MOZ_KEYWORDS...................................... 3            1.4% 
MOZ_ANNO_ATTRIBUTES............................... 2            0.90% 
MOZ_ANNOS......................................... 2            0.90% 
MOZ_BOOKMARKS_ROOTS............................... 2            0.90% 
MOZ_HOSTS......................................... 2            0.90% 
MOZ_INPUTHISTORY.................................. 2            0.90% 
MOZ_ITEMS_ANNOS................................... 2            0.90% 
SQLITE_SCHEMA..................................... 1            0.45% 
SQLITE_SEQUENCE................................... 1            0.45% 
SQLITE_STAT1...................................... 1            0.45% 

*** Page counts for all tables and indices separately *************************

MOZ_PLACES........................................ 63          28.5% 
MOZ_PLACES_URL_UNIQUEINDEX........................ 37          16.7% 
MOZ_HISTORYVISITS................................. 13           5.9% 
MOZ_FAVICONS...................................... 12           5.4% 
MOZ_HISTORYVISITS_PLACEDATEINDEX.................. 12           5.4% 
MOZ_PLACES_HOSTINDEX.............................. 11           5.0% 
MOZ_HISTORYVISITS_DATEINDEX....................... 10           4.5% 
MOZ_PLACES_GUID_UNIQUEINDEX....................... 9            4.1% 
MOZ_PLACES_LASTVISITDATEINDEX..................... 7            3.2% 
MOZ_HISTORYVISITS_FROMINDEX....................... 6            2.7% 
MOZ_PLACES_FAVICONINDEX........................... 5            2.3% 
MOZ_PLACES_FRECENCYINDEX.......................... 5            2.3% 
MOZ_PLACES_VISITCOUNT............................. 5            2.3% 
SQLITE_AUTOINDEX_MOZ_FAVICONS_1................... 3            1.4% 
MOZ_ANNO_ATTRIBUTES............................... 1            0.45% 
MOZ_ANNOS......................................... 1            0.45% 
MOZ_ANNOS_PLACEATTRIBUTEINDEX..................... 1            0.45% 
MOZ_BOOKMARKS..................................... 1            0.45% 
MOZ_BOOKMARKS_GUID_UNIQUEINDEX.................... 1            0.45% 
MOZ_BOOKMARKS_ITEMINDEX........................... 1            0.45% 
MOZ_BOOKMARKS_ITEMLASTMODIFIEDINDEX............... 1            0.45% 
MOZ_BOOKMARKS_PARENTINDEX......................... 1            0.45% 
MOZ_BOOKMARKS_ROOTS............................... 1            0.45% 
MOZ_HOSTS......................................... 1            0.45% 
MOZ_INPUTHISTORY.................................. 1            0.45% 
MOZ_ITEMS_ANNOS................................... 1            0.45% 
MOZ_ITEMS_ANNOS_ITEMATTRIBUTEINDEX................ 1            0.45% 
MOZ_KEYWORDS...................................... 1            0.45% 
MOZ_KEYWORDS_PLACEPOSTDATA_UNIQUEINDEX............ 1            0.45% 
SQLITE_AUTOINDEX_MOZ_ANNO_ATTRIBUTES_1............ 1            0.45% 
SQLITE_AUTOINDEX_MOZ_BOOKMARKS_ROOTS_1............ 1            0.45% 
SQLITE_AUTOINDEX_MOZ_HOSTS_1...................... 1            0.45% 
SQLITE_AUTOINDEX_MOZ_INPUTHISTORY_1............... 1            0.45% 
SQLITE_AUTOINDEX_MOZ_KEYWORDS_1................... 1            0.45% 
SQLITE_SCHEMA..................................... 1            0.45% 
SQLITE_SEQUENCE................................... 1            0.45% 
SQLITE_STAT1...................................... 1            0.45% 

*** All tables and indices ****************************************************

Percentage of total database...................... 100.0%    
Number of entries................................. 154969    
Bytes of storage consumed......................... 7241728   
Bytes of payload.................................. 4969404     68.6% 
Average payload per entry......................... 32.07     
Average unused bytes per entry.................... 11.15     
Average fanout.................................... 14.00     
Maximum payload per entry......................... 7640      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 14        
Primary pages used................................ 207       
Overflow pages used............................... 0         
Total pages used.................................. 221       
Unused bytes on index pages....................... 448010      97.7% 
Unused bytes on primary pages..................... 1280642     18.9% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 1728652     23.9% 

*** All tables ****************************************************************

Percentage of total database......................  44.8%    
Number of entries................................. 28530     
Bytes of storage consumed......................... 3244032   
Bytes of payload.................................. 2508257     77.3% 
Average payload per entry......................... 87.92     
Average unused bytes per entry.................... 20.13     
Average fanout.................................... 28.00     
Maximum payload per entry......................... 7640      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 3         
Primary pages used................................ 96        
Overflow pages used............................... 0         
Total pages used.................................. 99        
Unused bytes on index pages....................... 97551       99.23% 
Unused bytes on primary pages..................... 476741      15.2% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 574292      17.7% 

*** All indices ***************************************************************

Percentage of total database......................  55.2%    
Number of entries................................. 126439    
Bytes of storage consumed......................... 3997696   
Bytes of payload.................................. 2461147     61.6% 
Average payload per entry......................... 19.47     
Average unused bytes per entry.................... 9.13      
Average fanout.................................... 11.00     
Maximum payload per entry......................... 7259      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 11        
Primary pages used................................ 111       
Overflow pages used............................... 0         
Total pages used.................................. 122       
Unused bytes on index pages....................... 350459      97.2% 
Unused bytes on primary pages..................... 803901      22.1% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 1154360     28.9% 

*** Table MOZ_ANNO_ATTRIBUTES and all its indices *****************************

Percentage of total database......................   0.90%   
Number of entries................................. 24        
Bytes of storage consumed......................... 65536     
Bytes of payload.................................. 721          1.1% 
Average payload per entry......................... 30.04     
Average unused bytes per entry.................... 2696.46   
Maximum payload per entry......................... 43        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 2         
Overflow pages used............................... 0         
Total pages used.................................. 2         
Unused bytes on primary pages..................... 64715       98.7% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 64715       98.7% 

*** Table MOZ_ANNO_ATTRIBUTES w/o any indices *********************************

Percentage of total database......................   0.45%   
Number of entries................................. 12        
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 355          1.1% 
B-tree depth...................................... 1         
Average payload per entry......................... 29.58     
Average unused bytes per entry.................... 2696.42   
Maximum payload per entry......................... 42        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32357       98.7% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32357       98.7% 

*** Index SQLITE_AUTOINDEX_MOZ_ANNO_ATTRIBUTES_1 of table MOZ_ANNO_ATTRIBUTES *

Percentage of total database......................   0.45%   
Number of entries................................. 12        
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 366          1.1% 
B-tree depth...................................... 1         
Average payload per entry......................... 30.50     
Average unused bytes per entry.................... 2696.50   
Maximum payload per entry......................... 43        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32358       98.7% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32358       98.7% 

*** Table MOZ_ANNOS and all its indices ***************************************

Percentage of total database......................   0.90%   
Number of entries................................. 390       
Bytes of storage consumed......................... 65536     
Bytes of payload.................................. 13986       21.3% 
Average payload per entry......................... 35.86     
Average unused bytes per entry.................... 128.22    
Maximum payload per entry......................... 127       
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 2         
Overflow pages used............................... 0         
Total pages used.................................. 2         
Unused bytes on primary pages..................... 50006       76.3% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 50006       76.3% 

*** Table MOZ_ANNOS w/o any indices *******************************************

Percentage of total database......................   0.45%   
Number of entries................................. 195       
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 12115       37.0% 
B-tree depth...................................... 1         
Average payload per entry......................... 62.13     
Average unused bytes per entry.................... 101.04    
Maximum payload per entry......................... 127       
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 19702       60.1% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 19702       60.1% 

*** Index MOZ_ANNOS_PLACEATTRIBUTEINDEX of table MOZ_ANNOS ********************

Percentage of total database......................   0.45%   
Number of entries................................. 195       
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 1871         5.7% 
B-tree depth...................................... 1         
Average payload per entry......................... 9.59      
Average unused bytes per entry.................... 155.41    
Maximum payload per entry......................... 10        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 30304       92.5% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 30304       92.5% 

*** Table MOZ_BOOKMARKS and all its indices ***********************************

Percentage of total database......................   2.3%    
Number of entries................................. 1565      
Bytes of storage consumed......................... 163840    
Bytes of payload.................................. 37104       22.6% 
Average payload per entry......................... 23.71     
Average unused bytes per entry.................... 77.62     
Maximum payload per entry......................... 518       
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 5         
Overflow pages used............................... 0         
Total pages used.................................. 5         
Unused bytes on primary pages..................... 121475      74.1% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 121475      74.1% 

*** Table MOZ_BOOKMARKS w/o any indices ***************************************

Percentage of total database......................   0.45%   
Number of entries................................. 313       
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 21937       66.9% 
B-tree depth...................................... 1         
Average payload per entry......................... 70.09     
Average unused bytes per entry.................... 29.90     
Maximum payload per entry......................... 518       
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 9358        28.6% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 9358        28.6% 

*** Indices of table MOZ_BOOKMARKS ********************************************

Percentage of total database......................   1.8%    
Number of entries................................. 1252      
Bytes of storage consumed......................... 131072    
Bytes of payload.................................. 15167       11.6% 
Average payload per entry......................... 12.11     
Average unused bytes per entry.................... 89.55     
Maximum payload per entry......................... 17        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 4         
Overflow pages used............................... 0         
Total pages used.................................. 4         
Unused bytes on primary pages..................... 112117      85.5% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 112117      85.5% 

*** Index MOZ_BOOKMARKS_GUID_UNIQUEINDEX of table MOZ_BOOKMARKS ***************

Percentage of total database......................   0.45%   
Number of entries................................. 313       
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 5207        15.9% 
B-tree depth...................................... 1         
Average payload per entry......................... 16.64     
Average unused bytes per entry.................... 85.03     
Maximum payload per entry......................... 17        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 26614       81.2% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 26614       81.2% 

*** Index MOZ_BOOKMARKS_ITEMINDEX of table MOZ_BOOKMARKS **********************

Percentage of total database......................   0.45%   
Number of entries................................. 313       
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 2547         7.8% 
B-tree depth...................................... 1         
Average payload per entry......................... 8.14      
Average unused bytes per entry.................... 93.53     
Maximum payload per entry......................... 9         
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 29274       89.3% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 29274       89.3% 

*** Index MOZ_BOOKMARKS_ITEMLASTMODIFIEDINDEX of table MOZ_BOOKMARKS **********

Percentage of total database......................   0.45%   
Number of entries................................. 313       
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 5020        15.3% 
B-tree depth...................................... 1         
Average payload per entry......................... 16.04     
Average unused bytes per entry.................... 85.63     
Maximum payload per entry......................... 17        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 26801       81.8% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 26801       81.8% 

*** Index MOZ_BOOKMARKS_PARENTINDEX of table MOZ_BOOKMARKS ********************

Percentage of total database......................   0.45%   
Number of entries................................. 313       
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 2393         7.3% 
B-tree depth...................................... 1         
Average payload per entry......................... 7.65      
Average unused bytes per entry.................... 94.02     
Maximum payload per entry......................... 9         
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 29428       89.8% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 29428       89.8% 

*** Table MOZ_BOOKMARKS_ROOTS and all its indices *****************************

Percentage of total database......................   0.90%   
Number of entries................................. 10        
Bytes of storage consumed......................... 65536     
Bytes of payload.................................. 94           0.14% 
Average payload per entry......................... 9.40      
Average unused bytes per entry.................... 6539.10   
Maximum payload per entry......................... 11        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 2         
Overflow pages used............................... 0         
Total pages used.................................. 2         
Unused bytes on primary pages..................... 65391       99.78% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 65391       99.78% 

*** Table MOZ_BOOKMARKS_ROOTS w/o any indices *********************************

Percentage of total database......................   0.45%   
Number of entries................................. 5         
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 47           0.14% 
B-tree depth...................................... 1         
Average payload per entry......................... 9.40      
Average unused bytes per entry.................... 6538.60   
Maximum payload per entry......................... 11        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32693       99.77% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32693       99.77% 

*** Index SQLITE_AUTOINDEX_MOZ_BOOKMARKS_ROOTS_1 of table MOZ_BOOKMARKS_ROOTS *

Percentage of total database......................   0.45%   
Number of entries................................. 5         
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 47           0.14% 
B-tree depth...................................... 1         
Average payload per entry......................... 9.40      
Average unused bytes per entry.................... 6539.60   
Maximum payload per entry......................... 11        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32698       99.79% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32698       99.79% 

*** Table MOZ_FAVICONS and all its indices ************************************

Percentage of total database......................   6.8%    
Number of entries................................. 941       
Bytes of storage consumed......................... 491520    
Bytes of payload.................................. 332765      67.7% 
Average payload per entry......................... 353.63    
Average unused bytes per entry.................... 164.00    
Average fanout.................................... 7.00      
Maximum payload per entry......................... 7640      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 2         
Primary pages used................................ 13        
Overflow pages used............................... 0         
Total pages used.................................. 15        
Unused bytes on index pages....................... 65340       99.70% 
Unused bytes on primary pages..................... 88980       20.9% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 154320      31.4% 

*** Table MOZ_FAVICONS w/o any indices ****************************************

Percentage of total database......................   5.4%    
Number of entries................................. 471       
Bytes of storage consumed......................... 393216    
Bytes of payload.................................. 297630      75.7% 
B-tree depth...................................... 2         
Average payload per entry......................... 631.91    
Average unused bytes per entry.................... 196.60    
Average fanout.................................... 11.00     
Non-sequential pages.............................. 6           54.5% 
Maximum payload per entry......................... 7640      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 11        
Overflow pages used............................... 0         
Total pages used.................................. 12        
Unused bytes on index pages....................... 32676       99.72% 
Unused bytes on primary pages..................... 59923       16.6% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 92599       23.5% 

*** Index SQLITE_AUTOINDEX_MOZ_FAVICONS_1 of table MOZ_FAVICONS ***************

Percentage of total database......................   1.4%    
Number of entries................................. 470       
Bytes of storage consumed......................... 98304     
Bytes of payload.................................. 35135       35.7% 
B-tree depth...................................... 2         
Average payload per entry......................... 74.76     
Average unused bytes per entry.................... 131.32    
Average fanout.................................... 3.00      
Non-sequential pages.............................. 1           50.0% 
Maximum payload per entry......................... 7259      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 2         
Overflow pages used............................... 0         
Total pages used.................................. 3         
Unused bytes on index pages....................... 32664       99.68% 
Unused bytes on primary pages..................... 29057       44.3% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 61721       62.8% 

*** Table MOZ_HISTORYVISITS and all its indices *******************************

Percentage of total database......................  18.6%    
Number of entries................................. 63470     
Bytes of storage consumed......................... 1343488   
Bytes of payload.................................. 882233      65.7% 
Average payload per entry......................... 13.90     
Average unused bytes per entry.................... 3.76      
Average fanout.................................... 10.00     
Maximum payload per entry......................... 21        
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 4         
Primary pages used................................ 37        
Overflow pages used............................... 0         
Total pages used.................................. 41        
Unused bytes on index pages....................... 130482      99.55% 
Unused bytes on primary pages..................... 108158       8.9% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 238640      17.8% 

*** Table MOZ_HISTORYVISITS w/o any indices ***********************************

Percentage of total database......................   5.9%    
Number of entries................................. 15873     
Bytes of storage consumed......................... 425984    
Bytes of payload.................................. 308447      72.4% 
B-tree depth...................................... 2         
Average payload per entry......................... 19.43     
Average unused bytes per entry.................... 2.40      
Average fanout.................................... 12.00     
Non-sequential pages.............................. 8           66.7% 
Maximum payload per entry......................... 21        
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 12        
Overflow pages used............................... 0         
Total pages used.................................. 13        
Unused bytes on index pages....................... 32668       99.69% 
Unused bytes on primary pages..................... 5435         1.4% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 38103        8.9% 

*** Indices of table MOZ_HISTORYVISITS ****************************************

Percentage of total database......................  12.7%    
Number of entries................................. 47597     
Bytes of storage consumed......................... 917504    
Bytes of payload.................................. 573786      62.5% 
Average payload per entry......................... 12.06     
Average unused bytes per entry.................... 4.21      
Average fanout.................................... 9.00      
Maximum payload per entry......................... 17        
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 3         
Primary pages used................................ 25        
Overflow pages used............................... 0         
Total pages used.................................. 28        
Unused bytes on index pages....................... 97814       99.50% 
Unused bytes on primary pages..................... 102723      12.5% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 200537      21.9% 

*** Index MOZ_HISTORYVISITS_DATEINDEX of table MOZ_HISTORYVISITS **************

Percentage of total database......................   4.5%    
Number of entries................................. 15865     
Bytes of storage consumed......................... 327680    
Bytes of payload.................................. 206221      62.9% 
B-tree depth...................................... 2         
Average payload per entry......................... 13.00     
Average unused bytes per entry.................... 4.65      
Average fanout.................................... 10.00     
Non-sequential pages.............................. 6           66.7% 
Maximum payload per entry......................... 13        
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 9         
Overflow pages used............................... 0         
Total pages used.................................. 10        
Unused bytes on index pages....................... 32596       99.48% 
Unused bytes on primary pages..................... 41128       13.9% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 73724       22.5% 

*** Index MOZ_HISTORYVISITS_FROMINDEX of table MOZ_HISTORYVISITS **************

Percentage of total database......................   2.7%    
Number of entries................................. 15869     
Bytes of storage consumed......................... 196608    
Bytes of payload.................................. 100292      51.0% 
B-tree depth...................................... 2         
Average payload per entry......................... 6.32      
Average unused bytes per entry.................... 3.06      
Average fanout.................................... 6.00      
Non-sequential pages.............................. 4           80.0% 
Maximum payload per entry......................... 7         
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 5         
Overflow pages used............................... 0         
Total pages used.................................. 6         
Unused bytes on index pages....................... 32702       99.80% 
Unused bytes on primary pages..................... 15927        9.7% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 48629       24.7% 

*** Index MOZ_HISTORYVISITS_PLACEDATEINDEX of table MOZ_HISTORYVISITS *********

Percentage of total database......................   5.4%    
Number of entries................................. 15863     
Bytes of storage consumed......................... 393216    
Bytes of payload.................................. 267273      68.0% 
B-tree depth...................................... 2         
Average payload per entry......................... 16.85     
Average unused bytes per entry.................... 4.93      
Average fanout.................................... 12.00     
Non-sequential pages.............................. 8           72.7% 
Maximum payload per entry......................... 17        
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 11        
Overflow pages used............................... 0         
Total pages used.................................. 12        
Unused bytes on index pages....................... 32516       99.23% 
Unused bytes on primary pages..................... 45668       12.7% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 78184       19.9% 

*** Table MOZ_HOSTS and all its indices ***************************************

Percentage of total database......................   0.90%   
Number of entries................................. 1256      
Bytes of storage consumed......................... 65536     
Bytes of payload.................................. 27640       42.2% 
Average payload per entry......................... 22.01     
Average unused bytes per entry.................... 26.18     
Maximum payload per entry......................... 49        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 2         
Overflow pages used............................... 0         
Total pages used.................................. 2         
Unused bytes on primary pages..................... 32888       50.2% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32888       50.2% 

*** Table MOZ_HOSTS w/o any indices *******************************************

Percentage of total database......................   0.45%   
Number of entries................................. 628       
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 14640       44.7% 
B-tree depth...................................... 1         
Average payload per entry......................... 23.31     
Average unused bytes per entry.................... 23.90     
Maximum payload per entry......................... 49        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 15012       45.8% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 15012       45.8% 

*** Index SQLITE_AUTOINDEX_MOZ_HOSTS_1 of table MOZ_HOSTS *********************

Percentage of total database......................   0.45%   
Number of entries................................. 628       
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 13000       39.7% 
B-tree depth...................................... 1         
Average payload per entry......................... 20.70     
Average unused bytes per entry.................... 28.46     
Maximum payload per entry......................... 47        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 17876       54.6% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 17876       54.6% 

*** Table MOZ_INPUTHISTORY and all its indices ********************************

Percentage of total database......................   0.90%   
Number of entries................................. 16        
Bytes of storage consumed......................... 65536     
Bytes of payload.................................. 642          0.98% 
Average payload per entry......................... 40.12     
Average unused bytes per entry.................... 4050.88   
Maximum payload per entry......................... 71        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 2         
Overflow pages used............................... 0         
Total pages used.................................. 2         
Unused bytes on primary pages..................... 64814       98.9% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 64814       98.9% 

*** Table MOZ_INPUTHISTORY w/o any indices ************************************

Percentage of total database......................   0.45%   
Number of entries................................. 8         
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 341          1.0% 
B-tree depth...................................... 1         
Average payload per entry......................... 42.62     
Average unused bytes per entry.................... 4047.38   
Maximum payload per entry......................... 71        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32379       98.8% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32379       98.8% 

*** Index SQLITE_AUTOINDEX_MOZ_INPUTHISTORY_1 of table MOZ_INPUTHISTORY *******

Percentage of total database......................   0.45%   
Number of entries................................. 8         
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 301          0.92% 
B-tree depth...................................... 1         
Average payload per entry......................... 37.62     
Average unused bytes per entry.................... 4054.38   
Maximum payload per entry......................... 65        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32435       99.0% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32435       99.0% 

*** Table MOZ_ITEMS_ANNOS and all its indices *********************************

Percentage of total database......................   0.90%   
Number of entries................................. 158       
Bytes of storage consumed......................... 65536     
Bytes of payload.................................. 9211        14.1% 
Average payload per entry......................... 58.30     
Average unused bytes per entry.................... 352.56    
Maximum payload per entry......................... 384       
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 2         
Overflow pages used............................... 0         
Total pages used.................................. 2         
Unused bytes on primary pages..................... 55704       85.0% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 55704       85.0% 

*** Table MOZ_ITEMS_ANNOS w/o any indices *************************************

Percentage of total database......................   0.45%   
Number of entries................................. 79        
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 8649        26.4% 
B-tree depth...................................... 1         
Average payload per entry......................... 109.48    
Average unused bytes per entry.................... 300.54    
Maximum payload per entry......................... 384       
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 23743       72.5% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 23743       72.5% 

*** Index MOZ_ITEMS_ANNOS_ITEMATTRIBUTEINDEX of table MOZ_ITEMS_ANNOS *********

Percentage of total database......................   0.45%   
Number of entries................................. 79        
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 562          1.7% 
B-tree depth...................................... 1         
Average payload per entry......................... 7.11      
Average unused bytes per entry.................... 404.57    
Maximum payload per entry......................... 9         
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 31961       97.5% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 31961       97.5% 

*** Table MOZ_KEYWORDS and all its indices ************************************

Percentage of total database......................   1.4%    
Number of entries................................. 0         
Bytes of storage consumed......................... 98304     
Bytes of payload.................................. 0            0.0% 
Average payload per entry......................... 0.0       
Average unused bytes per entry.................... 0.0       
Maximum payload per entry......................... 0         
Entries that use overflow......................... 0         
Primary pages used................................ 3         
Overflow pages used............................... 0         
Total pages used.................................. 3         
Unused bytes on primary pages..................... 98280       99.976% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 98280       99.976% 

*** Table MOZ_KEYWORDS w/o any indices ****************************************

Percentage of total database......................   0.45%   
Number of entries................................. 0         
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 0            0.0% 
B-tree depth...................................... 1         
Average payload per entry......................... 0.0       
Average unused bytes per entry.................... 0.0       
Maximum payload per entry......................... 0         
Entries that use overflow......................... 0         
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32760       99.976% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32760       99.976% 

*** Indices of table MOZ_KEYWORDS *********************************************

Percentage of total database......................   0.90%   
Number of entries................................. 0         
Bytes of storage consumed......................... 65536     
Bytes of payload.................................. 0            0.0% 
Average payload per entry......................... 0.0       
Average unused bytes per entry.................... 0.0       
Maximum payload per entry......................... 0         
Entries that use overflow......................... 0         
Primary pages used................................ 2         
Overflow pages used............................... 0         
Total pages used.................................. 2         
Unused bytes on primary pages..................... 65520       99.976% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 65520       99.976% 

*** Index MOZ_KEYWORDS_PLACEPOSTDATA_UNIQUEINDEX of table MOZ_KEYWORDS ********

Percentage of total database......................   0.45%   
Number of entries................................. 0         
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 0            0.0% 
B-tree depth...................................... 1         
Average payload per entry......................... 0.0       
Average unused bytes per entry.................... 0.0       
Maximum payload per entry......................... 0         
Entries that use overflow......................... 0         
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32760       99.976% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32760       99.976% 

*** Index SQLITE_AUTOINDEX_MOZ_KEYWORDS_1 of table MOZ_KEYWORDS ***************

Percentage of total database......................   0.45%   
Number of entries................................. 0         
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 0            0.0% 
B-tree depth...................................... 1         
Average payload per entry......................... 0.0       
Average unused bytes per entry.................... 0.0       
Maximum payload per entry......................... 0         
Entries that use overflow......................... 0         
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32760       99.976% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32760       99.976% 

*** Table MOZ_PLACES and all its indices **************************************

Percentage of total database......................  64.3%    
Number of entries................................. 87087     
Bytes of storage consumed......................... 4653056   
Bytes of payload.................................. 3659043     78.6% 
Average payload per entry......................... 42.02     
Average unused bytes per entry.................... 7.93      
Average fanout.................................... 17.00     
Maximum payload per entry......................... 1867      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 8         
Primary pages used................................ 134       
Overflow pages used............................... 0         
Total pages used.................................. 142       
Unused bytes on index pages....................... 252188      96.2% 
Unused bytes on primary pages..................... 438258      10.0% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 690446      14.8% 

*** Table MOZ_PLACES w/o any indices ******************************************

Percentage of total database......................  28.5%    
Number of entries................................. 10894     
Bytes of storage consumed......................... 2064384   
Bytes of payload.................................. 1838131     89.0% 
B-tree depth...................................... 2         
Average payload per entry......................... 168.73    
Average unused bytes per entry.................... 14.10     
Average fanout.................................... 62.00     
Non-sequential pages.............................. 30          48.4% 
Maximum payload per entry......................... 1867      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 62        
Overflow pages used............................... 0         
Total pages used.................................. 63        
Unused bytes on index pages....................... 32207       98.3% 
Unused bytes on primary pages..................... 121406       6.0% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 153613       7.4% 

*** Indices of table MOZ_PLACES ***********************************************

Percentage of total database......................  35.7%    
Number of entries................................. 76193     
Bytes of storage consumed......................... 2588672   
Bytes of payload.................................. 1820912     70.3% 
Average payload per entry......................... 23.90     
Average unused bytes per entry.................... 7.05      
Average fanout.................................... 11.00     
Maximum payload per entry......................... 1823      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 7         
Primary pages used................................ 72        
Overflow pages used............................... 0         
Total pages used.................................. 79        
Unused bytes on index pages....................... 219981      95.9% 
Unused bytes on primary pages..................... 316852      13.4% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 536833      20.7% 

*** Index MOZ_PLACES_FAVICONINDEX of table MOZ_PLACES *************************

Percentage of total database......................   2.3%    
Number of entries................................. 10891     
Bytes of storage consumed......................... 163840    
Bytes of payload.................................. 83178       50.8% 
B-tree depth...................................... 2         
Average payload per entry......................... 7.64      
Average unused bytes per entry.................... 4.40      
Average fanout.................................... 5.00      
Non-sequential pages.............................. 3           75.0% 
Maximum payload per entry......................... 8         
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 4         
Overflow pages used............................... 0         
Total pages used.................................. 5         
Unused bytes on index pages....................... 32711       99.83% 
Unused bytes on primary pages..................... 15213       11.6% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 47924       29.3% 

*** Index MOZ_PLACES_FRECENCYINDEX of table MOZ_PLACES ************************

Percentage of total database......................   2.3%    
Number of entries................................. 10891     
Bytes of storage consumed......................... 163840    
Bytes of payload.................................. 76772       46.9% 
B-tree depth...................................... 2         
Average payload per entry......................... 7.05      
Average unused bytes per entry.................... 4.99      
Average fanout.................................... 5.00      
Non-sequential pages.............................. 3           75.0% 
Maximum payload per entry......................... 9         
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 4         
Overflow pages used............................... 0         
Total pages used.................................. 5         
Unused bytes on index pages....................... 32714       99.84% 
Unused bytes on primary pages..................... 21616       16.5% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 54330       33.2% 

*** Index MOZ_PLACES_GUID_UNIQUEINDEX of table MOZ_PLACES *********************

Percentage of total database......................   4.1%    
Number of entries................................. 10887     
Bytes of storage consumed......................... 294912    
Bytes of payload.................................. 196000      66.5% 
B-tree depth...................................... 2         
Average payload per entry......................... 18.00     
Average unused bytes per entry.................... 6.07      
Average fanout.................................... 9.00      
Non-sequential pages.............................. 5           62.5% 
Maximum payload per entry......................... 18        
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 8         
Overflow pages used............................... 0         
Total pages used.................................. 9         
Unused bytes on index pages....................... 32581       99.43% 
Unused bytes on primary pages..................... 33545       12.8% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 66126       22.4% 

*** Index MOZ_PLACES_HOSTINDEX of table MOZ_PLACES ****************************

Percentage of total database......................   5.0%    
Number of entries................................. 10885     
Bytes of storage consumed......................... 360448    
Bytes of payload.................................. 237383      65.9% 
B-tree depth...................................... 2         
Average payload per entry......................... 21.81     
Average unused bytes per entry.................... 8.29      
Average fanout.................................... 11.00     
Non-sequential pages.............................. 7           70.0% 
Maximum payload per entry......................... 49        
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 10        
Overflow pages used............................... 0         
Total pages used.................................. 11        
Unused bytes on index pages....................... 32473       99.10% 
Unused bytes on primary pages..................... 57782       17.6% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 90255       25.0% 

*** Index MOZ_PLACES_LASTVISITDATEINDEX of table MOZ_PLACES *******************

Percentage of total database......................   3.2%    
Number of entries................................. 10889     
Bytes of storage consumed......................... 229376    
Bytes of payload.................................. 150784      65.7% 
B-tree depth...................................... 2         
Average payload per entry......................... 13.85     
Average unused bytes per entry.................... 4.21      
Average fanout.................................... 7.00      
Non-sequential pages.............................. 4           66.7% 
Maximum payload per entry......................... 14        
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 6         
Overflow pages used............................... 0         
Total pages used.................................. 7         
Unused bytes on index pages....................... 32651       99.64% 
Unused bytes on primary pages..................... 13179        6.7% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 45830       20.0% 

*** Index MOZ_PLACES_URL_UNIQUEINDEX of table MOZ_PLACES **********************

Percentage of total database......................  16.7%    
Number of entries................................. 10859     
Bytes of storage consumed......................... 1212416   
Bytes of payload.................................. 1010666     83.4% 
B-tree depth...................................... 2         
Average payload per entry......................... 93.07     
Average unused bytes per entry.................... 15.42     
Average fanout.................................... 37.00     
Non-sequential pages.............................. 16          44.4% 
Maximum payload per entry......................... 1823      
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 36        
Overflow pages used............................... 0         
Total pages used.................................. 37        
Unused bytes on index pages....................... 24134       73.7% 
Unused bytes on primary pages..................... 143261      12.1% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 167395      13.8% 

*** Index MOZ_PLACES_VISITCOUNT of table MOZ_PLACES ***************************

Percentage of total database......................   2.3%    
Number of entries................................. 10891     
Bytes of storage consumed......................... 163840    
Bytes of payload.................................. 66129       40.4% 
B-tree depth...................................... 2         
Average payload per entry......................... 6.07      
Average unused bytes per entry.................... 5.97      
Average fanout.................................... 5.00      
Non-sequential pages.............................. 3           75.0% 
Maximum payload per entry......................... 8         
Entries that use overflow......................... 0            0.0% 
Index pages used.................................. 1         
Primary pages used................................ 4         
Overflow pages used............................... 0         
Total pages used.................................. 5         
Unused bytes on index pages....................... 32717       99.84% 
Unused bytes on primary pages..................... 32256       24.6% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 64973       39.7% 

*** Table SQLITE_SCHEMA *******************************************************

Percentage of total database......................   0.45%   
Number of entries................................. 36        
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 5188        15.8% 
B-tree depth...................................... 1         
Average payload per entry......................... 144.11    
Average unused bytes per entry.................... 758.58    
Maximum payload per entry......................... 379       
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 27309       83.3% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 27309       83.3% 

*** Table SQLITE_SEQUENCE *****************************************************

Percentage of total database......................   0.45%   
Number of entries................................. 1         
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 15           0.046% 
B-tree depth...................................... 1         
Average payload per entry......................... 15.00     
Average unused bytes per entry.................... 32741.00  
Maximum payload per entry......................... 15        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 32741       99.918% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 32741       99.918% 

*** Table SQLITE_STAT1 ********************************************************

Percentage of total database......................   0.45%   
Number of entries................................. 15        
Bytes of storage consumed......................... 32768     
Bytes of payload.................................. 762          2.3% 
B-tree depth...................................... 1         
Average payload per entry......................... 50.80     
Average unused bytes per entry.................... 2128.20   
Maximum payload per entry......................... 62        
Entries that use overflow......................... 0            0.0% 
Primary pages used................................ 1         
Overflow pages used............................... 0         
Total pages used.................................. 1         
Unused bytes on primary pages..................... 31923       97.4% 
Unused bytes on overflow pages.................... 0         
Unused bytes on all pages......................... 31923       97.4% 

*** Definitions ***************************************************************

Page size in bytes

    The number of bytes in a single page of the database file.  
    Usually 1024.

Number of pages in the whole file

    The number of 32768-byte pages that go into forming the complete
    database

Pages that store data

    The number of pages that store data, either as primary B*Tree pages or
    as overflow pages.  The number at the right is the data pages divided by
    the total number of pages in the file.

Pages on the freelist

    The number of pages that are not currently in use but are reserved for
    future use.  The percentage at the right is the number of freelist pages
    divided by the total number of pages in the file.

Pages of auto-vacuum overhead

    The number of pages that store data used by the database to facilitate
    auto-vacuum. This is zero for databases that do not support auto-vacuum.

Number of tables in the database

    The number of tables in the database, including the SQLITE_SCHEMA table
    used to store schema information.

Number of indices

    The total number of indices in the database.

Number of defined indices

    The number of indices created using an explicit CREATE INDEX statement.

Number of implied indices

    The number of indices used to implement PRIMARY KEY or UNIQUE constraints
    on tables.

Size of the file in bytes

    The total amount of disk space used by the entire database files.

Bytes of user payload stored

    The total number of bytes of user payload stored in the database. The
    schema information in the SQLITE_SCHEMA table is not counted when
    computing this number.  The percentage at the right shows the payload
    divided by the total file size.

Percentage of total database

    The amount of the complete database file that is devoted to storing
    information described by this category.

Number of entries

    The total number of B-Tree key/value pairs stored under this category.

Bytes of storage consumed

    The total amount of disk space required to store all B-Tree entries
    under this category.  The is the total number of pages used times
    the pages size.

Bytes of payload

    The amount of payload stored under this category.  Payload is the data
    part of table entries and the key part of index entries.  The percentage
    at the right is the bytes of payload divided by the bytes of storage 
    consumed.

Average payload per entry

    The average amount of payload on each entry.  This is just the bytes of
    payload divided by the number of entries.

Average unused bytes per entry

    The average amount of free space remaining on all pages under this
    category on a per-entry basis.  This is the number of unused bytes on
    all pages divided by the number of entries.

Non-sequential pages

    The number of pages in the table or index that are out of sequence.
    Many filesystems are optimized for sequential file access so a small
    number of non-sequential pages might result in faster queries,
    especially for larger database files that do not fit in the disk cache.
    Note that after running VACUUM, the root page of each table or index is
    at the beginning of the database file and all other pages are in a
    separate part of the database file, resulting in a single non-
    sequential page.

Maximum payload per entry

    The largest payload size of any entry.

Entries that use overflow

    The number of entries that user one or more overflow pages.

Total pages used

    This is the number of pages used to hold all information in the current
    category.  This is the sum of index, primary, and overflow pages.

Index pages used

    This is the number of pages in a table B-tree that hold only key (rowid)
    information and no data.

Primary pages used

    This is the number of B-tree pages that hold both key and data.

Overflow pages used

    The total number of overflow pages used for this category.

Unused bytes on index pages

    The total number of bytes of unused space on all index pages.  The
    percentage at the right is the number of unused bytes divided by the
    total number of bytes on index pages.

Unused bytes on primary pages

    The total number of bytes of unused space on all primary pages.  The
    percentage at the right is the number of unused bytes divided by the
    total number of bytes on primary pages.

Unused bytes on overflow pages

    The total number of bytes of unused space on all overflow pages.  The
    percentage at the right is the number of unused bytes divided by the
    total number of bytes on overflow pages.

Unused bytes on all pages

    The total number of bytes of unused space on all primary and overflow 
    pages.  The percentage at the right is the number of unused bytes 
    divided by the total number of bytes.

*******************************************************************************
The entire text of this report can be sourced into any SQL database
engine for further analysis.  All of the text above is an SQL comment.
The data used to generate this report follows:
*/
BEGIN;
CREATE TABLE space_used(
   name clob,        -- Name of a table or index in the database file
   tblname clob,     -- Name of associated table
   is_index boolean, -- TRUE if it is an index, false for a table
   nentry int,       -- Number of entries in the BTree
   leaf_entries int, -- Number of leaf entries
   depth int,        -- Depth of the b-tree
   payload int,      -- Total amount of data stored in this table or index
   ovfl_payload int, -- Total amount of data stored on overflow pages
   ovfl_cnt int,     -- Number of entries that use overflow
   mx_payload int,   -- Maximum payload size
   int_pages int,    -- Number of interior pages used
   leaf_pages int,   -- Number of leaf pages used
   ovfl_pages int,   -- Number of overflow pages used
   int_unused int,   -- Number of unused bytes on interior pages
   leaf_unused int,  -- Number of unused bytes on primary pages
   ovfl_unused int,  -- Number of unused bytes on overflow pages
   gap_cnt int,      -- Number of gaps in the page layout
   compressed_size int  -- Total bytes stored on disk
);
INSERT INTO space_used VALUES('sqlite_schema','sqlite_schema',0,36,36,1,5188,0,0,379,0,1,0,0,27309,0,0,32768);
INSERT INTO space_used VALUES('moz_places','moz_places',0,10955,10894,2,1838131,0,0,1867,1,62,0,32207,121406,0,30,2064384);
INSERT INTO space_used VALUES('moz_historyvisits','moz_historyvisits',0,15884,15873,2,308447,0,0,21,1,12,0,32668,5435,0,8,425984);
INSERT INTO space_used VALUES('moz_inputhistory','moz_inputhistory',0,8,8,1,341,0,0,71,0,1,0,0,32379,0,0,32768);
INSERT INTO space_used VALUES('sqlite_autoindex_moz_inputhistory_1','moz_inputhistory',1,8,8,1,301,0,0,65,0,1,0,0,32435,0,0,32768);
INSERT INTO space_used VALUES('moz_hosts','moz_hosts',0,628,628,1,14640,0,0,49,0,1,0,0,15012,0,0,32768);
INSERT INTO space_used VALUES('sqlite_autoindex_moz_hosts_1','moz_hosts',1,628,628,1,13000,0,0,47,0,1,0,0,17876,0,0,32768);
INSERT INTO space_used VALUES('moz_bookmarks','moz_bookmarks',0,313,313,1,21937,0,0,518,0,1,0,0,9358,0,0,32768);
INSERT INTO space_used VALUES('moz_bookmarks_roots','moz_bookmarks_roots',0,5,5,1,47,0,0,11,0,1,0,0,32693,0,0,32768);
INSERT INTO space_used VALUES('sqlite_autoindex_moz_bookmarks_roots_1','moz_bookmarks_roots',1,5,5,1,47,0,0,11,0,1,0,0,32698,0,0,32768);
INSERT INTO space_used VALUES('moz_keywords','moz_keywords',0,0,0,1,0,0,0,0,0,1,0,0,32760,0,0,32768);
INSERT INTO space_used VALUES('sqlite_autoindex_moz_keywords_1','moz_keywords',1,0,0,1,0,0,0,0,0,1,0,0,32760,0,0,32768);
INSERT INTO space_used VALUES('sqlite_sequence','sqlite_sequence',0,1,1,1,15,0,0,15,0,1,0,0,32741,0,0,32768);
INSERT INTO space_used VALUES('moz_favicons','moz_favicons',0,481,471,2,297630,0,0,7640,1,11,0,32676,59923,0,6,393216);
INSERT INTO space_used VALUES('sqlite_autoindex_moz_favicons_1','moz_favicons',1,471,470,2,35135,0,0,7259,1,2,0,32664,29057,0,1,98304);
INSERT INTO space_used VALUES('moz_anno_attributes','moz_anno_attributes',0,12,12,1,355,0,0,42,0,1,0,0,32357,0,0,32768);
INSERT INTO space_used VALUES('sqlite_autoindex_moz_anno_attributes_1','moz_anno_attributes',1,12,12,1,366,0,0,43,0,1,0,0,32358,0,0,32768);
INSERT INTO space_used VALUES('moz_annos','moz_annos',0,195,195,1,12115,0,0,127,0,1,0,0,19702,0,0,32768);
INSERT INTO space_used VALUES('moz_items_annos','moz_items_annos',0,79,79,1,8649,0,0,384,0,1,0,0,23743,0,0,32768);
INSERT INTO space_used VALUES('sqlite_stat1','sqlite_stat1',0,15,15,1,762,0,0,62,0,1,0,0,31923,0,0,32768);
INSERT INTO space_used VALUES('moz_places_faviconindex','moz_places',1,10894,10891,2,83178,0,0,8,1,4,0,32711,15213,0,3,163840);
INSERT INTO space_used VALUES('moz_places_hostindex','moz_places',1,10894,10885,2,237383,0,0,49,1,10,0,32473,57782,0,7,360448);
INSERT INTO space_used VALUES('moz_places_visitcount','moz_places',1,10894,10891,2,66129,0,0,8,1,4,0,32717,32256,0,3,163840);
INSERT INTO space_used VALUES('moz_places_frecencyindex','moz_places',1,10894,10891,2,76772,0,0,9,1,4,0,32714,21616,0,3,163840);
INSERT INTO space_used VALUES('moz_places_lastvisitdateindex','moz_places',1,10894,10889,2,150784,0,0,14,1,6,0,32651,13179,0,4,229376);
INSERT INTO space_used VALUES('moz_historyvisits_placedateindex','moz_historyvisits',1,15873,15863,2,267273,0,0,17,1,11,0,32516,45668,0,8,393216);
INSERT INTO space_used VALUES('moz_historyvisits_fromindex','moz_historyvisits',1,15873,15869,2,100292,0,0,7,1,5,0,32702,15927,0,4,196608);
INSERT INTO space_used VALUES('moz_historyvisits_dateindex','moz_historyvisits',1,15873,15865,2,206221,0,0,13,1,9,0,32596,41128,0,6,327680);
INSERT INTO space_used VALUES('moz_bookmarks_itemindex','moz_bookmarks',1,313,313,1,2547,0,0,9,0,1,0,0,29274,0,0,32768);
INSERT INTO space_used VALUES('moz_bookmarks_parentindex','moz_bookmarks',1,313,313,1,2393,0,0,9,0,1,0,0,29428,0,0,32768);
INSERT INTO space_used VALUES('moz_bookmarks_itemlastmodifiedindex','moz_bookmarks',1,313,313,1,5020,0,0,17,0,1,0,0,26801,0,0,32768);
INSERT INTO space_used VALUES('moz_places_url_uniqueindex','moz_places',1,10894,10859,2,1010666,0,0,1823,1,36,0,24134,143261,0,16,1212416);
INSERT INTO space_used VALUES('moz_places_guid_uniqueindex','moz_places',1,10894,10887,2,196000,0,0,18,1,8,0,32581,33545,0,5,294912);
INSERT INTO space_used VALUES('moz_bookmarks_guid_uniqueindex','moz_bookmarks',1,313,313,1,5207,0,0,17,0,1,0,0,26614,0,0,32768);
INSERT INTO space_used VALUES('moz_annos_placeattributeindex','moz_annos',1,195,195,1,1871,0,0,10,0,1,0,0,30304,0,0,32768);
INSERT INTO space_used VALUES('moz_items_annos_itemattributeindex','moz_items_annos',1,79,79,1,562,0,0,9,0,1,0,0,31961,0,0,32768);
INSERT INTO space_used VALUES('moz_keywords_placepostdata_uniqueindex','moz_keywords',1,0,0,1,0,0,0,0,0,1,0,0,32760,0,0,32768);
COMMIT;

This page last modified on  2020-06-18 21:18:56 UTC


c2: Quirks, Caveats, and Gotchas In SQLite
c5: quirks.html
c4:
1. Overview


The SQL language is a "standard".
Even so, no two SQL database engines work exactly alike.
Every SQL implementation has it own peculiarities and oddities,
and SQLite is no exception to this rule.


This document strives to highlight the principal differences
between SQLite and other SQL implementations, as an aid to developers
that are porting to or from SQLite or who are trying to build a
system that works across multiple database engines.


If you are an SQLite user whose has stumbled over some quirk of
SQLite that is not mentioned here, please let the developers know
by posting a brief message on the
SQLite Forum.

2. SQLite Is Embedded, Not Client-Server


Whenever comparing SQLite to other SQL database engines like
SQL Server, PostgreSQL, MySQL, or Oracle, it is important first of all
to realize that SQLite is not intended as a replacement or competitor to
any of those systems.  SQLite is serverless.  There is no separate
server process that manages the database.  An application interacts
with the database engine using function calls, not by sending messages
to a separate process or thread.


The fact that SQLite is embedded and serverless instead of being
client/server is a feature, not a bug.


Client/server databases like MySQL, PostgreSQL, SQL Server, Oracle, and
others are an important component of modern systems.  
These systems solve an important problem.  
But SQLite solves a different problem.
Both SQLite and client/server databases have their role.
Developers who are comparing SQLite against other SQL database engines need
to clearly understand this distinction.


See the Appropriate Uses For SQLite document for additional information.

3. Flexible Typing


SQLite is flexible with regard to datatypes.  Datatypes are advisory
rather than mandatory.


Some commentators say that SQLite is "weakly typed" and that other
SQL databases are "strongly typed".  We consider these terms to be
inaccurate and even pejorative.  We prefer to say that SQLite is 
"flexibly typed" and that other SQL database engines are
"rigidly typed".


See the Datatypes in SQLite document for a detailed
discussion of the type system in SQLite.


The key point is that SQLite is very forgiving of the type of data that
you put into the database.  For example, if a column has a datatype of
"INTEGER" and the application inserts a text string into that column,
SQLite will first try to convert the text string into an integer, just like
every other SQL database engine.  Thus, if one inserts '1234' into
an INTEGER column, that value is converted into an integer 1234 and stored.
But, if you insert a non-numeric string like 'wxyz' into an INTEGER
column, unlike other SQL databases, SQLite does not throw an error.  Instead,
SQLite stores the actual string value in the column.


Similarly, SQLite allows you to store a 2000-character string into a
column of type VARCHAR(50).  Other SQL implementations would either throw
an error or truncate the string.  SQLite stores the entire 2000-character
string with no loss of information and without complaint.


Where this ends up causing problems is when developers do some initial
coding work using SQLite and get their application working, but then try
to convert to another database like PostgreSQL or SQL Server for deployment.
If the application is initially taking advantage of SQLite's flexible typing,
then it will fail when moved to another database that uses a more rigid
and unforgiving type enforcement policy.


Flexible typing is a feature of SQLite, not a bug.  Flexible typing
is about freedom.
Nevertheless, we recognize that this feature does sometimes cause
confusion for developers who are accustomed to working with
other databases that are more strict with regard to data type rules.
In retrospect, perhaps it would have been less confusing if SQLite had merely
implemented an ANY datatype so that developers could explicitly state
when they wanted to use flexible typing, rather than making flexible
typing the default.
As an accommodation for those who expect rigid typing, SQLite version 3.37.0
(2021-11-27) introduced the option of STRICT tables.
These either impose
the mandatory datatype constraints found in other SQL database engines,
or allow the explicit ANY datatype to retain SQLite's flexible typing.

3.1. No Separate BOOLEAN Datatype


Unlike most other SQL implementations,
SQLite does not have a separate BOOLEAN data type.
Instead, TRUE and FALSE are (normally) represented as integers 1 and 0,
respectively.
This does not seem to cause many problems, as we seldom get complaints
about it.  But it is important to recognize.


Beginning with SQLite version 3.23.0 (2018-04-02), SQLite also
recognizes TRUE and FALSE keywords as aliases for integer values 1 and 0,
respectively.
This provides better compatibility with other SQL implementations.
But for backwards compatibility, if there are columns named TRUE or
FALSE, then the keywords are treated as identifiers referencing those
columns, rather than BOOLEAN literals.

3.2. No Separate DATETIME Datatype


SQLite has no DATETIME datatype.
Instead, dates and times can be stored in any of these ways:


 As a TEXT string in the ISO-8601 format.  Example: '2018-04-02 12:13:46'.
 As an INTEGER number of seconds since 1970 (also known as "unix time").
 As a REAL value that is the fractional 
     Julian day number.



The built-in date and time functions of SQLite understand date/times in
all of the formats above, and can freely change between them.
Which format you use, is entirely up to your application.

3.3. The datatype is optional


Because SQLite is flexible and forgiving with regard to datatypes,
table columns can be created that have no specified datatype at all.
For example:
CREATE TABLE t1(a,b,c,d);

The table "t1" has four columns "a", "b", "c", and "d" that have
no particular datatype assigned.  You can store anything you want in
any of those columns.

4. Foreign Key Enforcement Is Off By Default

SQLite has parsed foreign key constraints for time out of mind,
but added the ability to actually enforce those constraints much later,
with version 3.6.19 (2009-10-14).  By the time foreign key constraint
enforcement was added, there were already countless millions of databases
in circulation that contained foreign key constraints, some of which
were not correct.  To avoid breaking those legacy databases, foreign key
constraint enforcement is turned off by default in SQLite.

Applications can activate foreign key enforcement at run-time using
the PRAGMA foreign_keys statement.  Or, foreign key enforcement can
be activated at compile-time using the
-DSQLITE_DEFAULT_FOREIGN_KEYS=1 compile-time option.

5. PRIMARY KEYs Can Sometimes Contain NULLs


Usually (the exceptions are INTEGER PRIMARY KEY tables and
WITHOUT ROWID tables) a PRIMARY KEY in an SQLite table is really
the same as a UNIQUE constraint.  Due to an historical oversight,
the column values of such a PRIMARY KEY are allowed to be NULL.
This is a bug, but by the time the problem was discovered there
where so many databases in circulation that depended on the bug that
the decision was made to support the buggy behavior moving forward.

The value of an INTEGER PRIMARY KEY column must always be a 
non-NULL integer.  The PRIMARY KEY columns of a WITHOUT ROWID
table are also required to be non-NULL.

6. Aggregate Queries Can Contain Non-Aggregate Result Columns
That Are Not In The GROUP BY Clause


In most SQL implementations, output columns of an aggregate query
may only reference aggregate functions or columns named in the
GROUP BY clause.  It does not make good sense to reference an ordinary
column in an aggregate query because each output row might be composed
from two or more rows in the input table(s).


SQLite does not enforce this restriction.
The output columns from an aggregate query can be arbitrary expressions
that include columns not found in GROUP BY clause.
This feature has two uses:



With SQLite (but not any other SQL implementation that we know of) if
an aggregate query contains a single min() or max() function, then the
values of columns used in the output are taken from the row where
the min() or max() value was achieved.  If two or more rows have the
same min() or max() value, then the columns values will be chosen arbitrarily
from one of those rows.

For example to find the highest paid employee:
SELECT max(salary), first_name, last_name FROM employee;


In the query above, the values for the first_name and last_name columns
will correspond to the row that satisfied the max(salary) condition.


If a query contains no aggregate functions at all, then a GROUP BY
clause can be added as a substitute for the DISTINCT ON clause.  In other words,
output rows are filtered so that only one row is shown for each distinct
set of values in the GROUP BY clause.  If two or more output rows would
have otherwise had the same set of values for the GROUP BY columns, then
one of the rows is chosen arbitrarily.  (SQLite supports DISTINCT but not
DISTINCT ON, whose functionality is provided instead by GROUP BY.)


7. Does Not Do Full Unicode Case Folding By Default


SQLite does not know about the upper-case/lower-case distinction
for all unicode characters.  SQL functions like
upper() and lower() only work on ASCII characters.  There are two
reasons for this:

 Though stable now, when SQLite was first designed, the rules for
     unicode case folding were still in flux.  That means that the
     behavior might have changed with each new unicode release, disrupting
     applications and corrupting indexes in the process.
 The tables necessary to do full and proper unicode case folding are
     larger than the whole SQLite library.


Full unicode case folding is supported in SQLite if it is compiled
with the -DSQLITE_ENABLE_ICU option and linked against the
International Components for Unicode
library.



8. Double-quoted String Literals Are Accepted


The SQL standard requires double-quotes around identifiers
and single-quotes around string literals.  For example:

 "this is a legal SQL column name"
 'this is an SQL string literal'


SQLite accepts both of the above.  But, in an effort to be compatible
with MySQL 3.x (which was one of the most widely used RDBMSes
when SQLite was first being designed) SQLite will also interpret
a double-quotes string as
string literal if it does not match any valid identifier.

This misfeature means that a misspelled double-quoted
identifier will be interpreted as a string literal, rather than generating
an error.
It also lures developers who are new to the SQL language into the
bad habit of using double-quoted string literals when they
really need to learn to use the correct single-quoted string literal form.

In hindsight, we should not have tried to make SQLite accept MySQL 3.x
syntax, and should have never allowed double-quoted string literals.
However, there are countless applications that make use of
double-quoted string literals and so we continue to support
that capability to avoid breaking legacy.

As of SQLite 3.27.0 (2019-02-07) the use of a double-quoted
string literal causes a warning message to be sent to the error log.

As of SQLite 3.29.0 (2019-07-10) the use of double-quoted
string literals can be disabled at run-time using the
SQLITE_DBCONFIG_DQS_DDL and SQLITE_DBCONFIG_DQS_DML actions
to sqlite3_db_config().  The default settings can be altered
at compile-time using the -DSQLITE_DQS=N compile-time
option.  Application developers are encouraged to compile using
-DSQLITE_DQS=0 in order to disable the double-quoted string literal
misfeature by default.  If that is not possible, then disable
double-quoted string literals for individual database connections
using C-code like this:

sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 0, (void*)0);
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 0, (void*)0);

Or, if double-quoted string literals are disabled by default, but need
to be selectively enabled for some historical database connections,
that can be done using the same C-code as shown above except with the
third parameter changed from 0 to 1.

9. Keywords Can Often Be Used As Identifiers


The SQL language is rich in keywords.
Most SQL implementations do not allow keywords to be used as identifiers
(names of tables or columns) unless they are enclosed in double-quotes.
But SQLite is more flexible.  Many keywords can be used as identifiers without
needing to be quoted, as long as those keywords are used in a context where
it is clear that they are intended to be an identifier.

For example, the following statement is valid in SQLite:
CREATE TABLE union(true INT, with BOOLEAN);


The same SQL statement will fail on every other SQL implementation that
we know of due to the use of keywords "union", "true", and "with" as
identifiers.

The ability to use keywords as identifiers promotes backwards compatibility.
As new keywords are added, legacy schemas that just happen to use those
keywords as table or column names continue to work.  However, the ability
to use a keyword as an identifier sometimes leads to surprising outcomes.
For example:
CREATE TRIGGER AFTER INSERT ON tableX BEGIN
  INSERT INTO tableY(b) VALUES(new.a);
END;

The trigger created by the previous statement is named "AFTER"
and it is a "BEFORE" trigger.  The "AFTER" token is used as an identifier
instead of as a keyword, as that is the only way to parse the statement.
Another example:
CREATE TABLE tableZ(INTEGER PRIMARY KEY);

The tableZ table has a single column named "INTEGER".  That column
has no datatype specified, but it is the PRIMARY KEY.
The column is not the INTEGER PRIMARY KEY for the table because
it has no datatype.  The "INTEGER" token is used as an identifier for the
column name, not as a datatype keyword.

10. Dubious SQL Is Allowed Without Any Error Or Warning


The original implementation of SQLite sought to follow
Postel's Law which
states in part "Be liberal in what you accept".
This used to be considered good design - that a system would accept
dodgy inputs and try to do the best it could without complaining too much.
But lately, people have come to realize that it is sometimes better to
be strict in what you accept, so as to more easily find errors in the
input.


11. AUTOINCREMENT Does Not Work The Same As MySQL

The AUTOINCREMENT feature in SQLite works differently than
it does in MySQL.  This often causes confusion for people who
initially learned SQL on MySQL and then start using SQLite, and
expect the two systems to work identically.

See the SQLite AUTOINCREMENT documentation for
detailed instructions on what AUTOINCREMENT does and does not do
in SQLite.

12. NUL Characters Are Allowed In Text Strings

NUL characters (ASCII code 0x00 and Unicode \u0000) may appear in
the middle of strings in SQLite.  This can lead to unexpected behavior.
See the "NUL characters in strings" document for further information.
This page last modified on  2022-11-16 22:21:04 UTC


c2: SQLite Version 3 Overview
c5: version3.html
c4:
Editorial Note:
This document was written in 2004 as a guide to programmers who were
transitioning from SQLite2 to SQLite3.
It is retained as part of the historical record of SQLite.
Modern programmers should refer to
more up-to-date documentation on SQLite available elsewhere
on this website.


SQLite Version 3 Overview


SQLite version 3.0 introduces important changes to the library, including:



A more compact format for database files.
Manifest typing and BLOB support.
Support for both UTF-8 and UTF-16 text.
User-defined text collating sequences.
64-bit ROWIDs.
Improved Concurrency.



This document is a quick introduction to the changes for SQLite 3.0
for users who are already familiar with SQLite version 2.8.


Naming Changes


SQLite version 2.8 will continue to be supported with bug fixes
for the foreseeable future.  In order to allow SQLite version 2.8
and SQLite version 3.0 to peacefully coexist, the names of key files
and APIs in SQLite version 3.0 have been changed to include the
character "3".  For example, the include file used by C programs
has been changed from "sqlite.h" to "sqlite3.h".  And the name of
the shell program used to interact with databases has been changed
from "sqlite.exe" to "sqlite3.exe".  With these changes, it is possible
to have both SQLite 2.8 and SQLite 3.0 installed on the same system at
the same time.  And it is possible for the same C program to link
against both SQLite 2.8 and SQLite 3.0 at the same time and to use
both libraries at the same time.


New File Format


The format used by SQLite database files has been completely revised.
The old version 2.1 format and the new 3.0 format are incompatible with
one another.  Version 2.8 of SQLite will not read a version 3.0 database
files and version 3.0 of SQLite will not read a version 2.8 database file.



To convert an SQLite 2.8 database into an SQLite 3.0 database, have
ready the command-line shells for both version 2.8 and 3.0.  Then
enter a command like the following:



sqlite OLD.DB .dump | sqlite3 NEW.DB



The new database file format uses B+trees for tables.  In a B+tree, all
data is stored in the leaves of the tree instead of in both the leaves and
the intermediate branch nodes.  The use of B+trees for tables allows for
better scalability and the storage of larger data fields without the use of
overflow pages.  Traditional B-trees are still used for indices.


The new file format also supports variable pages sizes between 512 and
65536 bytes.  The size of a page is stored in the file header so the
same library can read databases with different pages sizes, in theory,
though this feature has not yet been implemented in practice.



The new file format omits unused fields from its disk images.  For example,
indices use only the key part of a B-tree record and not the data.  So
for indices, the field that records the length of the data is omitted.
Integer values such as the length of key and data are stored using
a variable-length encoding so that only one or two bytes are required to
store the most common cases but up to 64-bits of information can be encoded
if needed. 
Integer and floating point data is stored on the disk in binary rather
than being converted into ASCII as in SQLite version 2.8.
These changes taken together result in database files that are typically
25% to 35% smaller than the equivalent files in SQLite version 2.8.



Details of the low-level B-tree format used in SQLite version 3.0 can
be found in header comments to the 
btreeInt.h
source file and in the file format documentation.


Manifest Typing and BLOB Support


SQLite version 2.8 will deal with data in various formats internally,
but when writing to the disk or interacting through its API, SQLite 2.8
always converts data into ASCII text.  SQLite 3.0, in contrast, exposes 
its internal data representations to the user and stores binary representations
to disk when appropriate.  The exposing of non-ASCII representations was
added in order to support BLOBs.



SQLite version 2.8 had the feature that any type of data could be stored
in any table column regardless of the declared type of that column.  This
feature is retained in version 3.0, though in a slightly modified form.
Each table column will store any type of data, though columns have an
affinity for the format of data defined by their declared datatype.
When data is inserted into a column, that column will make an attempt
to convert the data format into the column's declared type.   All SQL
database engines do this.  The difference is that SQLite 3.0 will 
still store the data even if a format conversion is not possible.



For example, if you have a table column declared to be of type "INTEGER"
and you try to insert a string, the column will look at the text string
and see if it looks like a number.  If the string does look like a number
it is converted into a number and into an integer if the number does not
have a fractional part, and stored that way.  But if the string is not
a well-formed number it is still stored as a string.  A column with a
type of "TEXT" tries to convert numbers into an ASCII-Text representation
before storing them.  But BLOBs are stored in TEXT columns as BLOBs because
you cannot in general convert a BLOB into text.



In most other SQL database engines the datatype is associated with
the table column that holds the data - with the data container.
In SQLite 3.0, the datatype is associated with the data itself, not
with its container.
Paul Graham in his book 
ANSI Common Lisp
calls this property "Manifest Typing".
Other writers have other definitions for the term "manifest typing",
so beware of confusion.  But by whatever name, that is the datatype
model supported by SQLite 3.0.



Additional information about datatypes in SQLite version 3.0 is
available
separately.


Support for UTF-8 and UTF-16


The new API for SQLite 3.0 contains routines that accept text as
both UTF-8 and UTF-16 in the native byte order of the host machine.
Each database file manages text as either UTF-8, UTF-16BE (big-endian),
or UTF-16LE (little-endian).  Internally and in the disk file, the
same text representation is used everywhere.  If the text representation
specified by the database file (in the file header) does not match
the text representation required by the interface routines, then text
is converted on-the-fly.
Constantly converting text from one representation to another can be
computationally expensive, so it is suggested that programmers choose a
single representation and stick with it throughout their application.



In the current implementation of SQLite, the SQL parser only works
with UTF-8 text.  So if you supply UTF-16 text it will be converted.
This is just an implementation issue and there is nothing to prevent
future versions of SQLite from parsing UTF-16 encoded SQL natively.



When creating new user-defined SQL functions and collating sequences,
each function or collating sequence can specify if it works with
UTF-8, UTF-16be, or UTF-16le.  Separate implementations can be registered
for each encoding.   If an SQL function or collating sequence is required
but a version for the current text encoding is not available, then 
the text is automatically converted.  As before, this conversion takes
computation time, so programmers are advised to pick a single
encoding and stick with it in order to minimize the amount of unnecessary
format juggling.



SQLite is not particular about the text it receives and is more than
happy to process text strings that are not normalized or even
well-formed UTF-8 or UTF-16.  Thus, programmers who want to store
ISO8859 data can do so using the UTF-8 interfaces.  As long as no
attempts are made to use a UTF-16 collating sequence or SQL function,
the byte sequence of the text will not be modified in any way.


User-defined Collating Sequences


A collating sequence is just a defined order for text.  When SQLite 3.0
sorts (or uses a comparison operator like "&lt;" or "&gt;=") the sort
order is first determined by the data type.



NULLs sort first
Numeric values sort next in numerical order
Text values come after numerics
BLOBs sort last



Collating sequences are used for comparing two text strings.
The collating sequence does not change the ordering of NULLs, numbers,
or BLOBs, only text.



A collating sequence is implemented as a function that takes the
two strings being compared as inputs and returns negative, zero, or
positive if the first string is less than, equal to, or greater than
the second.
SQLite 3.0 comes with a single built-in collating sequence named "BINARY"
which is implemented using the memcmp() routine from the standard C library.
The BINARY collating sequence works well for English text.  For other
languages or locales, alternative collating sequences may be preferred.



The decision of which collating sequence to use is controlled by the
COLLATE clause in SQL.  A COLLATE clause can occur on a table definition,
to define a default collating sequence to a table column, or on field
of an index, or in the ORDER BY clause of a SELECT statement.
Planned enhancements to SQLite are to include standard CAST() syntax
to allow the collating sequence of an expression to be defined.


64-bit ROWIDs


Every row of a table has a unique rowid.
If the table defines a column with the type "INTEGER PRIMARY KEY" then that
column becomes an alias for the rowid.  But with or without an INTEGER PRIMARY
KEY column, every row still has a rowid.



In SQLite version 3.0, the rowid is a 64-bit signed integer.
This is an expansion of SQLite version 2.8 which only permitted
rowids of 32-bits.



To minimize storage space, the 64-bit rowid is stored as a variable length
integer.  Rowids between 0 and 127 use only a single byte.  
Rowids between 0 and 16383 use just 2 bytes.  Up to 2097152 uses three
bytes.  And so forth.  Negative rowids are allowed but they always use
nine bytes of storage and so their use is discouraged.  When rowids
are generated automatically by SQLite, they will always be non-negative.


Improved Concurrency


SQLite version 2.8 allowed multiple simultaneous readers or a single
writer but not both.  SQLite version 3.0 allows one process to begin
writing the database while other processes continue to read.  The
writer must still obtain an exclusive lock on the database for a brief
interval in order to commit its changes, but the exclusive lock is no
longer required for the entire write operation.
A more detailed report on the locking
behavior of SQLite version 3.0 is available separately.



A limited form of table-level locking is now also available in SQLite.
If each table is stored in a separate database file, those separate
files can be attached to the main database (using the ATTACH command)
and the combined databases will function as one.  But locks will only
be acquired on individual files as needed.  So if you redefine "database"
to mean two or more database files, then it is entirely possible for
two processes to be writing to the same database at the same time.
To further support this capability, commits of transactions involving
two or more ATTACHed database are now atomic.


Credits


SQLite version 3.0 is made possible in part by AOL developers
supporting and embracing great Open-Source Software.

This page last modified on  2020-04-28 13:12:41 UTC


c2: sqldiff.exe: Database Difference Utility
c5: sqldiff.html
c4:
1. Usage


The sqldiff.exe binary is a command-line utility program that
displays content differences between SQLite databases.  Example
usage:

sqldiff &#91;options&#93; database1.sqlite database2.sqlite



The usual output is an SQL script that will transform
database1.sqlite (the "source" database) into database2.sqlite
(the "destination" database).  This behavior can be
altered using command-line switches:


--changeset FILE
Do not write changes to standard output.  Instead, write a (binary)
       changeset file into FILE.  The changeset can be interpreted using
       the session extension to SQLite.
--lib LIBRARY
-L LIBRARY
Load the shared library or DLL file LIBRARY into SQLite prior to
       computing the differences.  This can be used to add application-defined
       collating sequences that are required by the schema.
--primarykey
Use the schema-defined PRIMARY KEY instead of the rowid to
       pair rows in the source and destination database.  (See additional
       explanation below.)
--schema
Show only column name and table differences in the schema,
       not the table content
--summary
Show how many rows have changed on each table, but do not show
       the actual changes
--table TABLE
Show only the differences in content for TABLE, not for the
       entire database
--transaction
Wrap SQL output in a single large transaction
--vtab
Add support for handling FTS3, FTS5 and rtree virtual tables. 
       See below for details. 



2. How It Works

The sqldiff.exe utility works by finding rows in the source and
destination that are logical "pairs".  The default behavior is to
treat two rows as pairs if they are in tables with the same name
and they have the same rowid, or in the case of a WITHOUT ROWID
table if they have the same PRIMARY KEY.  Any differences in the
content of paired rows are output as UPDATEs.  Rows in the source
database that could not be paired are output as DELETEs.  Rows in
the destination database that could not be paired are output as
INSERTs.

The --primarykey flag changes the pairing algorithm slightly so
that the schema-declared PRIMARY KEY is always used for pairing,
even on tables that have a rowid.  This is often a better choice
for finding differences, however it can lead to missed differences in
the case of rows that have one or more PRIMARY KEY columns set to
NULL.

3. Limitations



The sqldiff.exe utility does not compute changesets for
either: rowid tables for which the rowid is inaccessible;
or tables which have no explicit primary key.
Given the --changeset option, sqldiff omits them from the comparison.
Examples of such tables are:

CREATE TABLE NilChangeset (
   -- inaccessible rowid due to hiding its aliases
   "rowid" TEXT,
   "oid" TEXT,
   "_rowid_" TEXT
);


and

CREATE TABLE NilChangeset (
   -- no explicit primary key
   "authorId" TEXT,
   "bookId" TEXT
);



When sqldiff is made to compare only such tables, no error occurs.
However, the result may be unexpected.
For example, the effect of this invocation:

sqldiff --changeset CHANGESET_OUT --table NilChangeset db1.sdb db2.sdb


will be to produce an empty file named "CHANGESET_OUT". See  session limitations for details.

The sqldiff.exe utility does not (currently) display differences in
TRIGGERs or VIEWs.


The sqldiff utility is not designed to support schema migrations
and is forgiving with respect to differing column definitions.
Normally, only the column names and their order are compared
for like-named tables before content comparison proceeds.

However, the single-table comparison option, with "sqlite_schema"
named, can be used to show or detect detailed schema differences
between a pair of databases.
When doing this, the output should not be used directly to modify a database.


By default, differences in the schema or content of virtual tables are
not reported on. 

However, if a virtual table implementation creates real tables (sometimes
referred to as "shadow" tables) within the database to store its data in, then
sqldiff.exe does calculate the difference between these. This can have
surprising effects if the resulting SQL script is then run on a database that
is not exactly the same as the source database. For several of SQLite's
bundled virtual tables (FTS3, FTS5, rtree and others), the surprising effects
may include corruption of the virtual table content.

 If the --vtab option is passed to sqldiff.exe, then it ignores all 
underlying shadow tables belonging to an FTS3, FTS5 or rtree virtual table
and instead includes the virtual table differences directly.


This page last modified on  2021-09-07 19:28:01 UTC


c2: Maintaining Private Branches Of SQLite
c5: privatebranch.html
c4:
1.  Introduction

SQLite is designed to meet most developer's needs without any 
changes or customization.  When changes are needed, they can normally
be accomplished using start-time (1)
or runtime
(2)
(3)
(4) configuration methods
or via compile-time options.  It is very rare that an application 
developer will need to edit the SQLite source code in order to 
incorporate SQLite into a product.

We call custom modifications to the SQLite source code that are held
for the use of a single application a "private branch".  When a private
branch becomes necessary, the application developer must take on the
task of keeping the private branch in synchronization with the public
SQLite sources.  This is tedious.  It can also be tricky, since while
the SQLite file format and published interfaces are very stable, the
internal implementation of SQLite changes quite rapidly.  Hundreds or
thousands of lines of code might change for any given SQLite point release.


This article outlines one possible method for keeping a private branch
of SQLite in sync with the public SQLite source code.
There are many ways of maintaining a private branch, of course.
Nobody is compelled to use the method describe here.
This article is not trying to impose a particular procedure on 
maintainers of private branches.  The point of this article is to offer
an example of one process for maintaining a private branch which can
be used as a template for designing processes best suited for the
circumstances of each individual project.


2.  The Basic Idea


We propose to use the
fossil software configuration management
system to set up two branches.  One branch (the "public branch" or "trunk")
contains the published SQLite sources and the other branch is the 
private branch which contains the code that is customized for the project.
Whenever a new public release of SQLite is made, that release is added to
the public branch and then the changes are merged into the private branch.

This document proposes to use
fossil,
but any other distributed software configuration management system such as
monotone or
mercurial (a.k.a. "hg"), or
git could serve just as well.
The concept will be the same, 
though the specifics of the procedure will vary.

The diagram at the right illustrates the concept.
One begins with a standard SQLite release.  For the
sake of example, suppose that one intends to create a
private branch off of SQLite version 3.6.15.  In the
diagram this is version (1).  The
maintainer makes an exact copy of the baseline
SQLite into the branch space, shown as version (2).
Note that (1) and (2) are exactly the same.  Then
the maintainer applies the private changes to 
version (2) resulting in version (3).  In other words,
version (3) is SQLite version 3.6.15 plus edits.

Later, SQLite version 3.6.16 is released, as shown 
by circle (4) in the diagram.  At the point, the private
branch maintainer does a merge which takes all of the
changes going from (1) to (4) and applies those changes to
(3).  The result is version (5), which is SQLite 3.6.16
plus edits.

There might be merge conflicts.  In other words, it might
be that the changes from (2) to (3) are incompatible with the
changes from (1) to (4).  In that case, the maintainer will
have to manually resolve the conflicts.  Hopefully conflicts
will not come up that often.  Conflicts are less likely to
occur when the private edits are kept to a minimum.

The cycle above can be repeated many times.  The
diagram shows a third SQLite release, 3.6.17 in
circle (6).  The private branch maintainer can do
another merge in order to incorporate the changes
moving from (4) to (6) into the private branch, resulting
in version (7).

3.  The Procedure

The remainder of this document will guide the reader through
the steps needed to maintain a private branch.  The general idea
is the same as outlined above.  This section merely provides more
detail.

We emphasize again that these steps are not intended to be the only
acceptable method for maintaining private branch.  This approach
is one of many.  Use this document as a baseline for preparing
project-specific procedures.  Do not be afraid to experiment.

3.1.  Obtain The Software

Fossil is a computer program
that must be installed on your machine before you use it.
Fortunately, installing fossil is very easy.  Fossil is a single
"*.exe" file that you simply download and run.  To uninstall fossil,
simply delete the exe file.  
Detailed instructions for installing and getting started with
fossil are available on the 
fossil website.

3.2.  Create A Project Repository

Create a fossil repository to host the private branch using the
following command:


fossil new private-project.fossil


You can call your project anything you like.  The ".fossil"
suffix is optional.  For this document, we will continue to call the
project "private-project.fossil".  Note that
private-project.fossil is an ordinary disk file (actually an
SQLite database) that will contain your complete project history.
You can make a backup of the project simply by making a copy of that
one file.

If you want to configure the new project, type:


fossil ui private-project.fossil


The "ui" command will cause fossil to run a miniature built-in webserver
and to launch your web-browser pointing
at that webserver.  You can use your web-browser to configure your project
in various ways.  See the instructions on the fossil website for additional
information.

Once the project repository is created, create an open checkout of the
project by moving to the directory where you want to keep all of the
project source code and typing:


fossil open private-project.fossil


You can have multiple checkouts of the same project if you want. 
And you can "clone" the repository to different machines so that multiple
developers can use it.  See the fossil website for further information.

3.3.  Installing The SQLite Baseline In Fossil

The repository created in the previous step is initially empty.  The
next step is to load the baseline SQLite release - circle (1) in the diagram
above.

Begin by obtaining a copy of SQLite in whatever form you use it.
The public SQLite you obtain should be as close to your private edited
copy as possible.  If your project uses the SQLite amalgamation, then
get a copy of the amalgamation.  If you use the preprocessed separate
source files, get those instead.  Put all the source files in the
checkout directory created in the previous step.

The source code in public SQLite releases uses unix line endings
(ASCII code 10: "newline" only, NL) and spaces instead of tabs.  If you will
be changing the line ending to windows-style line endings
(ASCII codes 13, 10: "carriage-return" and "newline"; CR-NL) or if you will be
changing space indents into tab indents, make that change now
before you check in the baseline.  The merging process will only work
well if the differences between the public and the private branches are
minimal.  If every single line of the source file is changed in the
private branch because you changed from NL to CR-NL line endings, then
the merge steps will not work correctly.

Let us assume that you are using the amalgamation source code.
Add the baseline to your project as follows:


fossil add sqlite3.c sqlite3.h


If you are using separate source files, name all of the source files instead
of just the two amalgamation source files.  Once this is done, commit your
changes as follows:


fossil commit


You will be prompted for a check-in comment.  Say whatever you like.
After the commit completes, your baseline will be part of the repository.
The following command, if you like, to see this on the "timeline":



fossil ui


That last command is the same "ui" command that we ran before.  It
starts a mini-webserver running and points your web browser at it.  But
this time we didn't have to specify the repository file because we are
located inside a checkout and so fossil can figure out the repository for
itself.  If you want to type in the repository filename as the second
argument, you can.  But it is optional.

If you do not want to use your web browser to view the new check-in,
you can get some information from the command-line using commands like
these:


fossil timeline
fossil info
fossil status


3.4.  Creating The Private Branch

The previous step created circle (1) in the diagram above.
This step will create circle (2).  Run the following command:

 
fossil branch new private trunk -bgcolor "#add8e8"


This command will create a new branch named "private" (you can use
a different name if you like) and assign it a background color
of light blue ("#add8e8").  You can omit the background color if you want,
though having a distinct background does make it easier to tell the
branch from the "trunk" (the public branch) on timeline displays.  You
can change the background color of the private branch or of the public
branch (the "trunk") using the web interface if you like.

The command above created the new branch.  But your checkout is
still on the trunk - a fact you can see by running the command:


fossil info


To change your check-out to the private branch, type:


fossil update private


You can run the "info" command again to verify that you are on the
private branch.  To go back to the public branch, type:


fossil update trunk


Normally, fossil will modify all the files in your checkout when switching
between the private and the public branches.  But at this point, the files
are identical in both branches so no modifications need to be made.

3.5.  Adding Customizations To The Code In The Private Branch

Now it is time to make the private, custom modifications to SQLite
which are the whole point of this exercise.  Switch to the private branch
(if you are not already there) using the "fossil update private"
command, then bring up the source files in your text editor and make
whatever changes you want to make.  Once you have finished making
changes, commit those changes using this command:


fossil commit


You will be prompted once again to enter a commit describing your
changes.  Then the commit will occur.  The commit creates a new checkin
in the repository that corresponds to circle (3) in the diagram above.

Now that the public and private branches are different, you can run
the "fossil update trunk" and "fossil update private"
commands and see that fossil really does change the files in the checkout
as you switch back and forth between branches.

Note that in the diagram above, we showed the private edits as a single
commit.  This was for clarity of presentation only.  There is nothing to stop
you from doing dozens or hundreds of separate tiny changes and committing
each separately.  In fact, making many small changes is the preferred way
to work.  The only reason for doing all the changes in a single commit
is that it makes the diagram easier to draw.

3.6.  Incorporating New Public SQLite Releases

Suppose that after a while (about a month, usually) a new version of
SQLite is released: 3.6.16.  You will want to incorporate this new
public version of SQLite into your repository in the public branch (the
trunk).  To do this, first change your repository over to the trunk:


fossil update trunk


Then download the new version of the SQLite sources and overwrite the
files that are in the checkout.

If you made NL to CR-NL line ending changes or space to tab
indentation changes in the original baseline, make the same changes
to the new source file.

Once everything is ready, run the "fossil commit" command to
check in the changes.  This creates circle (4) in the diagram above.

3.7.  Merging Public SQLite Updates Into The Private Branch

The next step is to move the changes in the public branch over into
the private branch.  In other words, we want to create circle (5) in the
diagram above.  Begin by changing to the private branch using
"fossil update private".  Then type this command:


fossil merge trunk


The "merge" command attempts to apply all the changes between
circles (1) and (4) to the files in the local checkout.  Note that
circle (5) has not been created yet.  You will need to run the
"commit" to create circle (5).

It might be that there are conflicts in the merge.  Conflicts
occur when the same line of code was changed in different ways between
circles (1) and (4) versus circles (2) and (3).  The merge command will
announce any conflicts and will include both versions of the conflicting
lines in the output.  You will need to bring up the files that contain
conflicts and manually resolve the conflicts.

After resolving conflicts, many users like to compile and test the
new version before committing it to the repository.  Or you can commit
first and test later.  Either way, run the "fossil commit"
command to check-in the circle (5) version.

3.8.  Further Updates

As new versions of SQLite are released, repeat steps 3.6 and 3.7 to
add changes in the new release to the private branch.
Additional private changes can be
made on the private branch in between releases if desired.

4.  Variations

Since this document was first written, the canonical SQLite source code
has been moved from the venerable CVS system into a Fossil repository at
http://www.sqlite.org/src.  This means that if you are working with
canonical SQLite source code (as opposed to the amalgamation source code
files, sqlite3.c and sqlite3.h) then you can create a private repository
simply by cloning the official repository:


fossil clone http://www.sqlite.org/src private-project.fossil


This command both creates the new repository and populates it with
all the latest SQLite code.  You can then create a private branch as
described in section 3.4.

When the private repository is created by cloning, incorporating new
public SQLite releases becomes much easier too.  To pull in all of the
latest changes from the public SQLite repository, simply move into
the open check-out and do:


fossil update


Then continue to merge the changes in "trunk" with your "private"
changes as described in section 3.7.
This page last modified on  2021-04-07 11:02:17 UTC


c2: Compile-time Options
c5: compile.html
c4:
1. Overview


For most purposes, SQLite can be built just fine using the default
compilation options. However, if required, the compile-time options
documented below can be used to 
omit SQLite features (resulting in
a smaller compiled library size) or to change the
default values of some parameters.



Every effort has been made to ensure that the various combinations
of compilation options work harmoniously and produce a working library.
Nevertheless, it is strongly recommended that the SQLite test-suite
be executed to check for errors before using an SQLite library built
with non-standard compilation options.





2. Recommended Compile-time Options

The following compile-time options are recommended for applications that
are able to use them, in order to minimized the number of CPU cycles and
the bytes of memory used by SQLite.
Not all of these compile-time options are usable by every application.
For example, the SQLITE_THREADSAFE=0 option is only usable by applications
that never access SQLite from more than one thread at a time.  And the
SQLITE_OMIT_PROGRESS_CALLBACK option is only usable by applications that
do not use the sqlite3_progress_handler() interface.  And so forth.

It is impossible to test every possible combination of compile-time
options for SQLite.  But the following set of compile-time options is
one configuration that is always fully tested.


SQLITE_DQS=0.
This setting disables the double-quoted string literal misfeature.

SQLITE_THREADSAFE=0.
Setting -DSQLITE_THREADSAFE=0 causes all of the mutex and thread-safety logic
in SQLite to be omitted.  This is the single compile-time option causes SQLite
to run about 2% faster and also reduces the size of the library by about 2%.
But the downside is that using the compile-time option means that SQLite can never
be used by more than a single thread at a time, even if each thread has its own
database connection.

SQLITE_DEFAULT_MEMSTATUS=0.
This setting causes the sqlite3_status() interfaces that track memory usage
to be disabled.  This helps the sqlite3_malloc() routines run much faster,
and since SQLite uses sqlite3_malloc() internally, this helps to make the
entire library faster.

SQLITE_DEFAULT_WAL_SYNCHRONOUS=1.
For maximum database safety following a power loss, the setting of
PRAGMA synchronous=FULL is recommended.  However, in WAL mode, complete
database integrity is guaranteed with PRAGMA synchronous=NORMAL.  With
PRAGMA synchronous=NORMAL in WAL mode, recent changes to the database might
be rolled back by a power loss, but the database will not be corrupted.
Furthermore, transaction commit is much faster in WAL mode using
synchronous=NORMAL than with the default synchronous=FULL.  For these
reasons, it is recommended that the synchronous setting be changed from
FULL to NORMAL when switching to WAL mode.  This compile-time option will
accomplish that.

SQLITE_LIKE_DOESNT_MATCH_BLOBS.
Historically, SQLite has allowed BLOB operands to the LIKE and GLOB
operators.  But having a BLOB as an operand of LIKE or GLOB complicates
and slows the LIKE optimization.  When this option is set, it means that
the LIKE and GLOB operators always return FALSE if either operand is a BLOB.
That simplifies the implementation of the LIKE optimization and allows
queries that use the LIKE optimization to run faster.

SQLITE_MAX_EXPR_DEPTH=0.
Setting the maximum expression parse-tree depth to zero disables all checking
of the expression parse-tree depth, which simplifies the code resulting in
faster execution, and helps the parse tree to use less memory.

SQLITE_OMIT_DECLTYPE.
By omitting the (seldom-needed) ability to return the declared type of
columns from the result set of query, prepared statements can be made
to consume less memory.

SQLITE_OMIT_DEPRECATED.
Omitting deprecated interfaces and features will not help SQLite to
run any faster.  It will reduce the library footprint, however.  And
it is the right thing to do.

SQLITE_OMIT_PROGRESS_CALLBACK.
The progress handler callback counter must be checked in the inner loop
of the bytecode engine.  By omitting this interface, a single conditional
is removed from the inner loop of the bytecode engine, helping SQL statements
to run slightly faster.

SQLITE_OMIT_SHARED_CACHE.
Omitting the possibility of using shared cache allows many conditionals
in performance-critical sections of the code to be eliminated.  This can
give a noticeable improvement in performance.

SQLITE_USE_ALLOCA.
Make use of alloca() for dynamically allocating temporary stack space for 
use within a single function, on systems that support alloca().  Without
this option, temporary space is allocated from the heap.

SQLITE_OMIT_AUTOINIT.
The SQLite library needs to be initialized using a call to
sqlite3_initialize() before certain interfaces are used.  
This initialization normally happens automatically the first time
it is needed.  However, with the SQLITE_OMIT_AUTOINIT option, the automatic
initialization is omitted.  This helps many API calls to run a little faster
(since they do not have to check to see if initialization has already occurred
and then run initialization if it has not previously been invoked) but it
also means that the application must call sqlite3_initialize() manually.
If SQLite is compiled with -DSQLITE_OMIT_AUTOINIT and a routine like
sqlite3_malloc() or sqlite3_vfs_find() or sqlite3_open() is invoked
without first calling sqlite3_initialize(), the likely result will be
a segfault.


When all of the recommended compile-time options above are used,
the SQLite library will be approximately 3% smaller and use about 5% fewer
CPU cycles.  So these options do not make a huge difference.  But in 
some design situations, every little bit helps.


3.  Platform Configuration


_HAVE_SQLITE_CONFIG_H
  If the _HAVE_SQLITE_CONFIG_H macro is defined
  then the SQLite source code will attempt to #include a file named "config.h".
  The "config.h" file usually contains other configuration options, especially
  "HAVE_INTERFACE" type options generated by autoconf scripts.

HAVE_FDATASYNC
  If the HAVE_FDATASYNC compile-time option is true, then the default VFS
  for unix systems will attempt to use fdatasync() instead of fsync() where
  appropriate.  If this flag is missing or false, then fsync() is always used.

HAVE_GMTIME_R
  If the HAVE_GMTIME_R option is true and if SQLITE_OMIT_DATETIME_FUNCS is true,
  then the CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP keywords will use
  the threadsafe "gmtime_r()" interface rather than "gmtime()".  In the usual case
  where SQLITE_OMIT_DATETIME_FUNCS is not defined or is false, then the
  built-in date and time functions are used to implement the CURRENT_TIME,
  CURRENT_DATE, and CURRENT_TIMESTAMP keywords and neither gmtime_r() nor
  gmtime() is ever called.

HAVE_ISNAN
  If the HAVE_ISNAN option is true, then SQLite invokes the system library isnan()
  function to determine if a double-precision floating point value is a NaN.
  If HAVE_ISNAN is undefined or false, then SQLite substitutes its own home-grown
  implementation of isnan().

HAVE_LOCALTIME_R
  If the HAVE_LOCALTIME_R option is true, then SQLite uses the threadsafe
  localtime_r() library routine instead of localtime()
  to help implement the localtime modifier
  to the built-in date and time functions.

HAVE_LOCALTIME_S
  If the HAVE_LOCALTIME_S option is true, then SQLite uses the threadsafe
  localtime_s() library routine instead of localtime()
  to help implement the localtime modifier
  to the built-in date and time functions.

HAVE_MALLOC_USABLE_SIZE
  If the HAVE_MALLOC_USABLE_SIZE option is true, then SQLite tries uses the
  malloc_usable_size() interface to find the size of a memory allocation obtained
  from the standard-library malloc() or realloc() routines.  This option is only
  applicable if the standard-library malloc() is used.  On Apple systems,
  "zone malloc" is used instead, and so this option is not applicable.  And, of
  course, if the application supplies its own malloc implementation using
  SQLITE_CONFIG_MALLOC then this option has no effect.
  
  If the HAVE_MALLOC_USABLE_SIZE option is omitted or is false, then SQLite 
  uses a wrapper around system malloc() and realloc() that enlarges each allocation
  by 8 bytes and writes the size of the allocation in the initial 8 bytes, and
  then SQLite also implements its own home-grown version of malloc_usable_size()
  that consults that 8-byte prefix to find the allocation size.  This approach
  works but it is suboptimal.  Applications are encouraged to use
  HAVE_MALLOC_USABLE_SIZE whenever possible.

HAVE_STRCHRNUL
  If the HAVE_STRCHRNUL option is true, then SQLite uses the strchrnul() library
  function.  If this option is missing or false, then SQLite substitutes its own
  home-grown implementation of strchrnul().

HAVE_USLEEP
  If the HAVE_USLEEP option is true, then the default unix VFS uses the
  usleep() system call to implement the xSleep method.  If this option is
  undefined or false, then xSleep on unix is implemented using sleep() which
  means that sqlite3_sleep() will have a minimum wait interval of 1000
  milliseconds regardless of its argument.  

HAVE_UTIME
  If the HAVE_UTIME option is true, then the built-in but non-standard
  "unix-dotfile" VFS will use the utime() system call, instead of utimes(),
  to set the last access time on the lock file.

SQLITE_BYTEORDER=(0|1234|4321)
  SQLite needs to know if the native byte order of the target CPU is
  big-endian or little-ending.  The SQLITE_BYTEORDER preprocessor is set
  to 4321 for big-endian machines and 1234 for little-endian machines, or
  it can be 0 to mean that the byte order must be determined at run-time.
  There are #ifdefs in the code that set SQLITE_BYTEORDER automatically
  for all common platforms and compilers.  However, it may be advantageous
  to set SQLITE_BYTEORDER appropriately when compiling SQLite for obscure
  targets.  If the target byte order cannot be determined at compile-time,
  then SQLite falls back to doing run-time checks, which always work, though
  with a small performance penalty.



4.  Options To Set Default Parameter Values


SQLITE_DEFAULT_AUTOMATIC_INDEX=&lt;0 or 1&gt;
  This macro determines the initial setting for PRAGMA automatic_index
  for newly opened database connections.
  For all versions of SQLite through 3.7.17,
  automatic indices are normally enabled for new database connections if
  this compile-time option is omitted.
  However, that might change in future releases of SQLite.
  See also: SQLITE_OMIT_AUTOMATIC_INDEX

SQLITE_DEFAULT_AUTOVACUUM=&lt;0 or 1 or 2&gt;
  This macro determines if SQLite creates databases with the 
  auto_vacuum flag set by default to OFF (0), FULL (1), or
  INCREMENTAL (2). The default value is 0 meaning that databases
  are created with auto-vacuum turned off.
  In any case the compile-time default may be overridden by the 
  PRAGMA auto_vacuum command.

SQLITE_DEFAULT_CACHE_SIZE=&lt;N&gt;
  This macro sets the default maximum size of the page-cache for each attached
  database.  A positive value means that the limit is N page.  If N is negative
  that means to limit the cache size to -N*1024 bytes.
  The suggested maximum cache size can be overridden by the 
  PRAGMA cache_size command. The default value is -2000, which translates
  into a maximum of 2048000 bytes per cache.

SQLITE_DEFAULT_FILE_FORMAT=&lt;1 or 4&gt;
  The default schema format number used by SQLite when creating
  new database files is set by this macro.  The schema formats are all
  very similar.  The difference between formats 1 and 4 is that format
  4 understands descending indices and has a tighter encoding for
  boolean values.

  All versions of SQLite since 3.3.0 (2006-01-10)
  can read and write any schema format
  between 1 and 4.  But older versions of SQLite might not be able to
  read formats greater than 1.  So that older versions of SQLite will
  be able to read and write database files created by newer versions
  of SQLite, the default schema format was set to 1 for SQLite versions
  through 3.7.9 (2011-11-01).  Beginning with 
  version 3.7.10 (2012-01-16), the default
  schema format is 4.

  The schema format number for a new database can be set at runtime using
  the PRAGMA legacy_file_format command.

SQLITE_DEFAULT_FILE_PERMISSIONS=N
  The default numeric file permissions for newly created database files
  under unix.  If not specified, the default is 0644 which means that
  the files is globally readable but only writable by the creator.

SQLITE_DEFAULT_FOREIGN_KEYS=&lt;0 or 1&gt;
  This macro determines whether enforcement of 
  foreign key constraints is enabled or disabled by default for
  new database connections.  Each database connection can always turn
  enforcement of foreign key constraints on and off and run-time using
  the foreign_keys pragma.  Enforcement of foreign key constraints
  is normally off by default, but if this compile-time parameter is
  set to 1, enforcement of foreign key constraints will be on by default.

SQLITE_DEFAULT_MMAP_SIZE=N
  This macro sets the default limit on the amount of memory that
  will be used for memory-mapped I/O
  for each open database file.  If the N
  is zero, then memory mapped I/O is disabled by default.  This
  compile-time limit and the SQLITE_MAX_MMAP_SIZE can be modified 
  at start-time using the
  sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) call, or at run-time
  using the mmap_size pragma.

SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=&lt;bytes&gt;
  This option sets the size limit on rollback journal files in
  persistent journal mode and
  exclusive locking mode and on the size of the
  write-ahead log file in WAL mode. When this 
  compile-time option is omitted there is no upper bound on the
  size of the rollback journals or write-ahead logs.  
  The journal file size limit
  can be changed at run-time using the journal_size_limit pragma.

SQLITE_DEFAULT_LOCKING_MODE=&lt;1 or 0&gt;
  If set to 1, then the default locking_mode is set to EXCLUSIVE.
  If omitted or set to 0 then the default locking_mode is NORMAL.

SQLITE_DEFAULT_LOOKASIDE=SZ,N
  Sets the default size of the lookaside memory allocator memory pool
  to N entries of SZ bytes each.  This setting can be modified at
  start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE) and/or
  as each database connection is opened using
  sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE).

SQLITE_DEFAULT_MEMSTATUS=&lt;1 or 0&gt;
  This macro is used to determine whether or not the features enabled and
  disabled using the SQLITE_CONFIG_MEMSTATUS argument to sqlite3_config()
  are available by default. The default value is 1 (SQLITE_CONFIG_MEMSTATUS
  related features enabled).
  
  The sqlite3_memory_used() and sqlite3_memory_highwater() interfaces,
  the sqlite3_status64(SQLITE_STATUS_MEMORY_USED) interface,
  and the SQLITE_MAX_MEMORY compile-time option are all non-functional
  when memory usage tracking is disabled.

SQLITE_DEFAULT_PCACHE_INITSZ=N
  This macro determines the number of pages initially allocated by the 
  page cache module when SQLITE_CONFIG_PAGECACHE configuration option is
  not use and memory for the page cache is obtained from sqlite3_malloc()
  instead.  The number of pages set by this macro are allocated in a single
  allocation, which reduces the load on the memory allocator.

SQLITE_DEFAULT_PAGE_SIZE=&lt;bytes&gt;
  This macro is used to set the default page-size used when a
  database is created. The value assigned must be a power of 2. The
  default value is 4096. The compile-time default may be overridden at 
  runtime by the PRAGMA page_size command.

SQLITE_DEFAULT_SYNCHRONOUS=&lt;0-3&gt;
  This macro determines the default value of the
  PRAGMA synchronous setting.  If not overridden at compile-time,
  the default setting is 2 (FULL).

SQLITE_DEFAULT_WAL_SYNCHRONOUS=&lt;0-3&gt;
  This macro determines the default value of the
  PRAGMA synchronous setting for database files that open in
  WAL mode.  If not overridden at compile-time, this value is the
  same as SQLITE_DEFAULT_SYNCHRONOUS.
  
  If SQLITE_DEFAULT_WAL_SYNCHRONOUS differs from SQLITE_DEFAULT_SYNCHRONOUS,
  and if the application has not modified the synchronous setting for
  the database file using the PRAGMA synchronous statement, then
  the synchronous setting is changed to value defined by
  SQLITE_DEFAULT_WAL_SYNCHRONOUS when the database connection switches
  into WAL mode for the first time.
  If the SQLITE_DEFAULT_WAL_SYNCHRONOUS value is not overridden at
  compile-time, then it will always be the same as
  SQLITE_DEFAULT_SYNCHRONOUS and so no automatic synchronous setting
  changes will ever occur.

SQLITE_DEFAULT_WAL_AUTOCHECKPOINT=&lt;pages&gt;
  This macro sets the default page count for the WAL
  automatic checkpointing feature.  If unspecified,
  the default page count is 1000.

SQLITE_DEFAULT_WORKER_THREADS=N
  This macro sets the default value for
  the SQLITE_LIMIT_WORKER_THREADS parameter.  The SQLITE_LIMIT_WORKER_THREADS
  parameter sets the maximum number of auxiliary threads that a single
  prepared statement will launch to assist it with a query.  If not specified,
  the default maximum is 0.
  The value set here cannot be more than SQLITE_MAX_WORKER_THREADS.

SQLITE_DQS=N
  This macro determines the default values for
  SQLITE_DBCONFIG_DQS_DDL and SQLITE_DBCONFIG_DQS_DML, which
  in turn how SQLite handles each double-quoted string literal.
  The "DQS" name stands for 
  "Double-Quoted String".
  The N argument should be an integer 0, 1, 2, or 3.
  
  SQLITE_DQSDouble-Quoted Strings Allowed
      Remarks
  In DDLIn DML
  3yesyesdefault
  2yesno&nbsp;
  1noyes&nbsp;
  0nonorecommended
  
  The recommended setting is 0, meaning that double-quoted
  strings are disallowed in all contexts.  However, the default
  setting is 3 for maximum compatibility with legacy applications.

SQLITE_EXTRA_DURABLE
  The SQLITE_EXTRA_DURABLE compile-time option that used to cause the default
  PRAGMA synchronous setting to be EXTRA, rather than FULL.  This option
  is no longer supported.  Use
  SQLITE_DEFAULT_SYNCHRONOUS=3 instead.

SQLITE_FTS3_MAX_EXPR_DEPTH=N
  This macro sets the maximum depth of the search tree that corresponds to
  the right-hand side of the MATCH operator in an FTS3 or FTS4 full-text
  index.  The full-text search uses a recursive algorithm, so the depth of
  the tree is limited to prevent using too much stack space.  The default
  limit is 12.  This limit is sufficient for up to 4095 search terms on the
  right-hand side of the MATCH operator and it holds stack space usage to 
  less than 2000 bytes.
  
  For ordinary FTS3/FTS4 queries, the search tree depth is approximately
  the base-2 logarithm of the number of terms in the right-hand side of the
  MATCH operator.  However, for phrase queries and NEAR queries the
  search tree depth is linear in the number of right-hand side terms.
  So the default depth limit of 12 is sufficient for up to 4095 ordinary
  terms on a MATCH, it is only sufficient for 11 or 12 phrase or NEAR
  terms.  Even so, the default is more than enough for most application.

SQLITE_LIKE_DOESNT_MATCH_BLOBS
  This compile-time option causes the LIKE operator to always return 
  False if either operand is a BLOB.  The default behavior of LIKE 
  is that BLOB operands are cast to TEXT before the comparison is done.
  
  This compile-time option makes SQLite run more efficiently when processing
  queries that use the LIKE operator, at the expense of breaking backwards
  compatibility.  However, the backwards compatibility break may be only
  a technicality.  There was a long-standing bug in the LIKE processing logic
  (see https://www.sqlite.org/src/info/05f43be8fdda9f) that caused it to
  misbehavior for BLOB operands and nobody observed that bug in nearly
  10 years of active use.  So for more users, it is probably safe to
  enable this compile-time option and thereby save a little CPU time
  on LIKE queries.
  
  This compile-time option affects the SQL LIKE operator only and has
  no impact on the sqlite3_strlike() C-language interface.

SQLITE_MAX_MEMORY=N
  This option limits the total amount of memory that SQLite will request
  from malloc() to N bytes.  Any attempt by SQLite to allocate
  new memory that would cause the sum of all allocations held by SQLite to exceed
  N bytes will result in an out-of-memory error.
  This is a hard upper limit.  See also the sqlite3_soft_heap_limit()
  interface.
  
  This limit is only functional if memory usage statistics are available via
  the sqlite3_memory_used() and sqlite3_status64(SQLITE_STATUS_MEMORY_USED)
  interfaces.  Without that memory usage information, SQLite has no way of
  knowing when it is about to go over the limit, and thus is unable to prevent
  the excess memory allocation.  Memory usage tracking is turned on by default,
  but can be disabled at compile-time using the SQLITE_DEFAULT_MEMSTATUS option,
  or at start-time using sqlite3_config(SQLITE_CONFIG_MEMSTATUS).

SQLITE_MAX_MMAP_SIZE=N
  This macro sets a hard upper bound on the amount of address space that
  can be used by any single database for memory-mapped I/O.
  Setting this value to 0 completely disables memory-mapped I/O and
  causes logic associated with memory-mapped I/O to be omitted from the
  build.  This option does change the default memory-mapped I/O address
  space size (set by SQLITE_DEFAULT_MMAP_SIZE or
  sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) or the
  run-time memory-mapped I/O address space size (set by
  sqlite3_file_control(SQLITE_FCNTL_MMAP_SIZE) or
  PRAGMA mmap_size) as long as those other settings are less than the
  maximum value defined here.

SQLITE_MAX_SCHEMA_RETRY=N
  Whenever the database schema changes, prepared statements are automatically
  reprepared to accommodate the new schema.  There is a race condition here
  in that if one thread is constantly changing the schema, another thread
  might spin on reparses and repreparations of a prepared statement and
  never get any real work done.  This parameter prevents an infinite loop
  by forcing the spinning thread to give up after a fixed number of attempts
  at recompiling the prepared statement.  The default setting is 50 which is
  more than adequate for most applications.

SQLITE_MAX_WORKER_THREADS=N
  Set an upper bound on the sqlite3_limit(db,SQLITE_LIMIT_WORKER_THREADS,N)
  setting that determines the maximum number of auxiliary threads that a single
  prepared statement will use to aid with CPU-intensive computations
  (mostly sorting).  See also the SQLITE_DEFAULT_WORKER_THREADS options.

SQLITE_MEMDB_DEFAULT_MAXSIZE=N
  Set the default size limit (in bytes) for in-memory databases created using
  sqlite3_deserialize().  This is just the default.  The limit can be
  changed at start-time using
  sqlite3_config(SQLITE_CONFIG_MEMDB_MAXSIZE,N)
  or at run-time for individual databases using the
  SQLITE_FCNTL_SIZE_LIMIT file-control.
  If no default is specified, 1073741824 is used.

SQLITE_MINIMUM_FILE_DESCRIPTOR=N
  The unix VFS will never use a file descriptor less than N.  The
  default value of N is 3.
  
  Avoiding the use of low-numbered file descriptors is a defense against
  accidental database corruption.  If a database file was opened using
  file descriptor 2, for example, and then an assert() failed and invoked
  write(2,...), that would likely cause database corruption by overwriting
  part of the database file with the assertion error message.  Using only
  higher-valued file descriptors avoids this potential problem.  The 
  protection against
  using low-numbered file descriptors can be disabled by setting this
  compile-time option to 0.

SQLITE_POWERSAFE_OVERWRITE=&lt;0 or 1&gt;
  This option changes the default assumption about powersafe overwrite
  for the underlying filesystems for the unix and windows VFSes.
  Setting SQLITE_POWERSAFE_OVERWRITE to 1 causes SQLite to assume that
  application-level writes cannot changes bytes outside the range of
  bytes written even if the write occurs just before a power loss.
  With SQLITE_POWERSAFE_OVERWRITE set to 0, SQLite assumes that other
  bytes in the same sector with a written byte might be changed or 
  damaged by a power loss.

SQLITE_PRINTF_PRECISION_LIMIT=N
  This option limits the maximum width and precision of substitutions
  for the printf() SQL function and the other C-language string
  formatting functions such as sqlite3_mprintf() and
  sqlite3_str_appendf().  This is turn can prevent a hostile or
  malfunctioning script from using excessive memory by invoking
  a format such as: "printf('%*s',2147483647,'hi')".
  A value for N of around 100000 is normally sufficient.
  
  The printf() SQL function is subject to the SQLITE_LIMIT_LENGTH
  limit of sqlite3_limit().  Hence any printf() result with a
  width or precision more than the SQLITE_LIMIT_LENGTH will cause
  an SQLITE_TOOBIG error.  However, the low-level formatting
  for the printf() function is done by a subroutine that does not
  have access to SQLITE_LIMIT_LENGTH.  So the low-level formatting
  is done into a memory allocation that might be considerably larger
  than SQLITE_LIMIT_LENGTH and the SQLITE_LIMIT_LENGTH check is only
  performed after all formatting is complete.  Thus there might be a
  transient buffer that exceeds SQLITE_LIMIT_LENGTH.  The
  SQLITE_PRINTF_PRECISION_LIMIT option is an additional check
  that prevents excess sizes for the transient buffer used inside
  the low-level formatting subroutine, prior to the
  SQLITE_LIMIT_LENGTH check.
  
  Be careful not to set SQLITE_PRINTF_PRECISION_LIMIT too low.
  SQLite uses its built-in printf() functionality to format the text
  of CREATE statements stored in the sqlite_schema table.  So
  SQLITE_PRINTF_PRECISION_LIMIT should be at least as big as the largest
  table, index, view, or trigger definition that you are likely to
  encounter.
  
  No error is raised if a width or precision exceeds
  SQLITE_PRINTF_PRECISION_LIMIT.  Instead, the large width or
  precision is silently truncated.
  
  The default value for SQLITE_PRINTF_PRECISION_LIMIT is 2147483647
  (0x7fffffff).


SQLITE_QUERY_PLANNER_LIMIT=N
  As part of the query planning process, SQLite enumerates all usable
  combinations of indexes and WHERE-clause constraints.  For certain
  pathological queries, the number of these index-and-constraint combinations
  can be very large, resulting in slow performance by the query planner.
  The SQLITE_QUERY_PLANNER_LIMIT value (in conjunction with the
  related SQLITE_QUERY_PLANNER_LIMIT_INCR setting) limits the number 
  of index-and-constraint combinations that the query planner will 
  consider, in order to prevent the query planner from using excess
  CPU time.  The default value for SQLITE_QUERY_PLANNER_LIMIT is set
  high enough so that is never reached for real-world queries.  The
  query planner search limit only applies to queries that are deliberately
  crafted to use excess planning time.

SQLITE_QUERY_PLANNER_LIMIT_INCR=N
  The SQLITE_QUERY_PLANNER_LIMIT option sets an initial baseline value
  for the maximum number of index-and-constraint combinations that the
  query planner consider.  The baseline query planner limit is increased
  by SQLITE_QUERY_PLANNER_LIMIT_INCR prior to processing each table of a
  join so that each table is guaranteed to be able to propose at least
  some index-and-constraint combinations to the optimizer even if prior
  tables of the join have exhausted the baseline limit.  The default
  value for both this compile-time option and the
  SQLITE_QUERY_PLANNER_LIMIT option are set high enough so that they should
  never be reached for real-world queries.

SQLITE_REVERSE_UNORDERED_SELECTS
  This option causes the PRAGMA reverse_unordered_selects setting to be
  enabled by default.  When enabled, SELECT statements that lack an
  ORDER BY clause will run in reverse order.
  This option is useful for detecting when applications (incorrectly)
  assume that the order of rows in a SELECT without an ORDER BY clause
  will always be the same.

SQLITE_SORTER_PMASZ=N
  If multi-threaded processing is enabled via the
  PRAGMA threads setting, then sort operations will
  attempt to start helper threads when the amount of content
  to be sorted exceeds the minimum of the cache_size and PMA Size
  determined by the SQLITE_CONFIG_PMASZ start-time option.
  This compile-time option sets the default value for the
  SQLITE_CONFIG_PMASZ start-time option.
  The default value is 250.

SQLITE_STMTJRNL_SPILL=N
  The SQLITE_STMTJRNL_SPILL compile-time option determines the
  default setting of the SQLITE_CONFIG_STMTJRNL_SPILL start-time
  setting.  That setting determines the size threshold above which
  statement journals are moved from memory to disk.

SQLITE_WIN32_MALLOC
  This option enables the use of the Windows Heap API functions for memory
  allocation instead of the standard library malloc() and free() routines.

YYSTACKDEPTH=&lt;max_depth&gt;
  This macro sets the maximum depth of the LALR(1) stack used by
  the SQL parser within SQLite.  The default value is 100.  A typical
  application will use less than about 20 levels of the stack.
  Developers whose applications contain SQL statements that 
  need more than 100 LALR(1) stack entries should seriously
  consider refactoring their SQL as it is likely to be well beyond
  the ability of any human to comprehend.


5.  Options To Set Size Limits

There are compile-time options that will set upper bounds
on the sizes of various structures in SQLite.  The compile-time
options normally set a hard upper bound that can be changed
at run-time on individual database connections using the
sqlite3_limit() interface.

The compile-time options for setting upper bounds are
documented separately.  The following is a list of
the available settings:


 SQLITE_MAX_ATTACHED  
 SQLITE_MAX_COLUMN  
 SQLITE_MAX_COMPOUND_SELECT  
 SQLITE_MAX_EXPR_DEPTH  
 SQLITE_MAX_FUNCTION_ARG  
 SQLITE_MAX_LENGTH  
 SQLITE_MAX_LIKE_PATTERN_LENGTH  
 SQLITE_MAX_PAGE_COUNT  
 SQLITE_MAX_SQL_LENGTH  
 SQLITE_MAX_VARIABLE_NUMBER  



6.  Options To Control Operating Characteristics


SQLITE_4_BYTE_ALIGNED_MALLOC
  On most systems, the malloc() system call returns a buffer that is
  aligned to an 8-byte boundary.  But on some systems (ex: windows) malloc()
  returns 4-byte aligned pointer.  This compile-time option must be used
  on systems that return 4-byte aligned pointers from malloc().

SQLITE_CASE_SENSITIVE_LIKE
  If this option is present, then the built-in LIKE operator will be
  case sensitive.  This same effect can be achieved at run-time using
  the case_sensitive_like pragma.

SQLITE_DIRECT_OVERFLOW_READ
  When this option is present, content contained in
  overflow pages of the database file is read directly from disk,
  bypassing the page cache, during read transactions.  In applications
  that do a lot of reads of large BLOBs, this option might improve read
  performance.

SQLITE_HAVE_ISNAN
  If this option is present, then SQLite will use the isnan() function from
  the system math library.  This is an alias for the HAVE_ISNAN configuration
  option.

SQLITE_MAX_ALLOCATION_SIZE=N
  This compile-time option sets an upper bound on the size of memory
  allocations that can be requested using sqlite3_malloc64(),
  sqlite3_realloc64(), and similar.  The default value is
  2,147,483,391 (0x7ffffeff) and this should be considered an
  upper bound.  Most applications can get by with an maximum allocation
  size of a few million bytes.
  
  This is a limit on the maximum size of any single memory allocation.
  It is not a limit on the total amount of memory allocated.
  
  Reducing the maximum size of individual memory allocations provides
  extra defense against denial-of-service attacks that attempt to exhaust
  system memory by doing many large allocations.  It is also an extra layer
  of defense against application bugs where the size of a memory allocation
  is computed using a signed 32-bit integer that could overflow &rarr;
  with a small maximum allocation size, such buggy memory allocation size
  computations are likely to be spotted sooner due to out-of-memory errors
  and before the integer actually overflows.

SQLITE_OS_OTHER=&lt;0 or 1&gt;
  The option causes SQLite to omit its built-in operating system interfaces
  for Unix, Windows, and OS/2.  The resulting library will have no default
  operating system interface.  Applications must use
  sqlite3_vfs_register() to register an appropriate interface before
  using SQLite.  Applications must also supply implementations for the
  sqlite3_os_init() and sqlite3_os_end() interfaces.  The usual practice
  is for the supplied sqlite3_os_init() to invoke sqlite3_vfs_register().
  SQLite will automatically invoke sqlite3_os_init() when it initializes.

  This option is typically used when building SQLite for an embedded
  platform with a custom operating system.

SQLITE_SECURE_DELETE
  This compile-time option changes the default setting of the
  secure_delete pragma.  When this option is not used, secure_delete defaults
  to off.  When this option is present, secure_delete defaults to on.

  The secure_delete setting causes deleted content to be overwritten with
  zeros.  There is a small performance penalty since additional I/O
  must occur.  On the other hand, secure_delete can prevent fragments of 
  sensitive information from lingering in unused parts of the database file 
  after it has been deleted.  See the documentation on the
  secure_delete pragma for additional information.

SQLITE_THREADSAFE=&lt;0 or 1 or 2&gt;
  This option controls whether or not code is included in SQLite to
  enable it to operate safely in a multithreaded environment.  The
  default is SQLITE_THREADSAFE=1 which is safe for use in a multithreaded
  environment.  When compiled with SQLITE_THREADSAFE=0 all mutexing code
  is omitted and it is unsafe to use SQLite in a multithreaded program.
  When compiled with SQLITE_THREADSAFE=2, SQLite can be used in a multithreaded
  program so long as no two threads attempt to use the same
  database connection (or any prepared statements derived from
  that database connection) at the same time.

  To put it another way, SQLITE_THREADSAFE=1 sets the default
  threading mode to Serialized.  SQLITE_THREADSAFE=2 sets the default
  threading mode to Multi-threaded.  And SQLITE_THREADSAFE=0 sets the
  threading mode to Single-threaded.

  The value of SQLITE_THREADSAFE can be determined at run-time
  using the sqlite3_threadsafe() interface.

  When SQLite has been compiled with SQLITE_THREADSAFE=1 or
  SQLITE_THREADSAFE=2 then the threading mode
  can be altered at run-time using the sqlite3_config() interface together
  with one of these verbs:

  
  SQLITE_CONFIG_SINGLETHREAD
  SQLITE_CONFIG_MULTITHREAD
  SQLITE_CONFIG_SERIALIZED
  

  The SQLITE_OPEN_NOMUTEX and
  SQLITE_OPEN_FULLMUTEX flags to sqlite3_open_v2() can also be used
  to adjust the threading mode of individual database connections
  at run-time.

  Note that when SQLite is compiled with SQLITE_THREADSAFE=0, the code
  to make SQLite threadsafe is omitted from the build.  When this occurs,
  it is impossible to change the threading mode at start-time or run-time.

  See the threading mode documentation for additional information
  on aspects of using SQLite in a multithreaded environment.

SQLITE_TEMP_STORE=&lt;0 through 3&gt;
  This option controls whether temporary files are stored on disk or
  in memory.  The meanings for various settings of this compile-time
  option are as follows:

  
  SQLITE_TEMP_STOREMeaning
  0Always use temporary files
  1Use files by default but allow the
  PRAGMA temp_store command to override
  2Use memory by default but allow the
  PRAGMA temp_store command to override
  3Always use memory
  

  The default setting is 1.  
  Additional information can be found in tempfiles.html.

SQLITE_TRACE_SIZE_LIMIT=N
  If this macro is defined to a positive integer N, then the length of
  strings and BLOB that are expanded into parameters in the output of
  sqlite3_trace() is limited to N bytes.  

SQLITE_TRUSTED_SCHEMA=&lt;0 or 1&gt;
  This macro determines the default value for the
  SQLITE_DBCONFIG_TRUSTED_SCHEMA and PRAGMA trusted_schema setting.
  If no alternative is specified, the trusted-schema setting defaults
  to ON (a value of 1) for legacy compatibility.  However, for best
  security, systems that implement
  application-defined SQL functions and/or virtual tables should
  consider changing the default to OFF.

SQLITE_USE_URI
  This option causes the URI filename process logic to be enabled by 
  default.  



7.  Options To Enable Features Normally Turned Off


SQLITE_ALLOW_URI_AUTHORITY
  URI filenames normally throws an error if the authority section is
  not either empty or "localhost".  However, if SQLite is compiled with
  the SQLITE_ALLOW_URI_AUTHORITY compile-time option, then the URI is
  converted into a Uniform Naming Convention (UNC) filename and passed
  down to the underlying operating system that way.  
  
  Some future versions of SQLite may change to enable this feature
  by default.

SQLITE_ALLOW_COVERING_INDEX_SCAN=&lt;0 or 1&gt;
  This C-preprocess macro determines the default setting of the
  SQLITE_CONFIG_COVERING_INDEX_SCAN configuration setting.  It defaults
  to 1 (on) which means that covering indices are used for full table
  scans where possible, in order to reduce I/O and improve performance.
  However, the use of a covering index for a full scan will cause results
  to appear in a different order from legacy, which could cause some
  (incorrectly-coded) legacy applications to break.  Hence, the covering
  index scan option can be disabled at compile-time on systems that what
  to minimize their risk of exposing errors in legacy applications.

SQLITE_ENABLE_8_3_NAMES=&lt;1 or 2&gt;
  If this C-preprocessor macro is defined, then extra code is
  included that allows SQLite to function on a filesystem that
  only support 8+3 filenames.  If the value of this macro is 1,
  then the default behavior is to continue to use long filenames and
  to only use 8+3 filenames if the 
  database connection is opened using URI filenames with
  the "8_3_names=1" query parameter.  If the value of
  this macro is 2, then the use of 8+3 filenames becomes the default
  but may be disabled on using the 8_3_names=0 query parameter.

SQLITE_ENABLE_API_ARMOR
  When defined, this C-preprocessor macro activates extra code that
  attempts to detect misuse of the SQLite API, such as passing in NULL
  pointers to required parameters or using objects after they have been
  destroyed.

SQLITE_ENABLE_ATOMIC_WRITE
  If this C-preprocessor macro is defined and if the
  xDeviceCharacteristics method of sqlite3_io_methods object for
  a database file reports (via one of the SQLITE_IOCAP_ATOMIC bits)
  that the filesystem supports atomic writes and if a transaction
  involves a change to only a single page of the database file,
  then the transaction commits with just a single write request of
  a single page of the database and no rollback journal is created
  or written.  On filesystems that support atomic writes, this
  optimization can result in significant speed improvements for
  small updates.  However, few filesystems support this capability
  and the code paths that check for this capability slow down write
  performance on systems that lack atomic write capability, so this
  feature is disabled by default.

SQLITE_ENABLE_BATCH_ATOMIC_WRITE
  This compile-time option enables SQLite to take advantage batch
  atomic write capabilities in the underlying filesystem.  As of
  SQLite version 3.21.0 (2017-10-24) this is only supported on
  F2FS.  However, the interface
  is implemented generically, using sqlite3_file_control() with
  SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and SQLITE_FCNTL_COMMIT_ATOMIC_WRITE
  so the capability can be added to other filesystem times in the
  future.  When this option is enabled, SQLite automatically detects
  that the underlying filesystem supports batch atomic writes, and
  when it does so it avoids writing the rollback journal for transaction
  control.  This can make transactions over twice as fast, while
  simultaneously reducing wear on SSD storage devices.

  Future versions of SQLite might enable the batch-atomic-write
  capability by default, at which point this compile-time option
  will become superfluous.

SQLITE_ENABLE_BYTECODE_VTAB
  This option enables the bytecode and tables_used virtual tables.

SQLITE_ENABLE_COLUMN_METADATA
  When this C-preprocessor macro is defined, SQLite includes some
  additional APIs that provide convenient access to meta-data about
  tables and queries.  The APIs that are enabled by this option are:

  
   sqlite3_column_database_name() 
   sqlite3_column_database_name16() 
   sqlite3_column_table_name() 
   sqlite3_column_table_name16() 
   sqlite3_column_origin_name() 
   sqlite3_column_origin_name16() 
  

SQLITE_ENABLE_DBPAGE_VTAB
  This option enables the SQLITE_DBPAGE virtual table.

SQLITE_ENABLE_DBSTAT_VTAB
  This option enables the dbstat virtual table.

SQLITE_ENABLE_DESERIALIZE
  This option was formerly used to enable
  the sqlite3_serialize() and sqlite3_deserialize()
  interfaces.  However, as of SQLite 3.36.0 (2021-06-18)
  those interfaces are enabled by default and a new
  compile-time option SQLITE_OMIT_DESERIALIZE is added
  to omit them.

SQLITE_ENABLE_EXPLAIN_COMMENTS
  This option adds extra logic to SQLite that inserts comment text into the
  output of EXPLAIN.  These extra comments use extra memory, thus
  making prepared statements larger and very slightly slower, and so they are
  turned off by default and in most application.  But some applications, such
  as the command-line shell for SQLite, value clarity of EXPLAIN output
  over raw performance and so this compile-time option is available to them.
  The SQLITE_ENABLE_EXPLAIN_COMMENTS compile-time option is also enabled
  automatically if SQLITE_DEBUG is enabled.

SQLITE_ENABLE_FTS3
  When this option is defined in the amalgamation, version 3
  of the full-text search engine is added to the build automatically.

SQLITE_ENABLE_FTS3_PARENTHESIS
  This option modifies the query pattern parser in FTS3 such that it
  supports operators AND and NOT (in addition to the usual OR and NEAR)
  and also allows query expressions to contain nested parenthesis.

SQLITE_ENABLE_FTS3_TOKENIZER
  This option enables the two-argument version of the fts3_tokenizer()
  interface.  The second argument to fts3_tokenizer() is suppose to be a
  pointer to a function (encoded as a BLOB) that implements an
  application defined tokenizer.  If hostile actors are able to run
  the two-argument version of fts3_tokenizer() with an arbitrary second
  argument, they could use crash or take control of the process. 
  
  Because of security concerns, the two-argument fts3_tokenizer() feature 
  was disabled beginning with Version 3.11.0 (2016-02-15)
  unless this compile-time option is used.
  Version 3.12.0 (2016-03-29) added the 
  sqlite3_db_config(db,SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER,1,0) interface
  that activates the two-argument version of fts3_tokenizer()
  for a specific database connection at run-time.

SQLITE_ENABLE_FTS4
  When this option is defined in the amalgamation, versions 3 and 4
  of the full-text search engine is added to the build automatically.

SQLITE_ENABLE_FTS5
  When this option is defined in the amalgamation, versions 5
  of the full-text search engine (fts5) is added to the build automatically.

SQLITE_ENABLE_GEOPOLY
  When this option is defined in the amalgamation, the Geopoly extension
  is included in the build.

SQLITE_ENABLE_ICU
  This option causes the 
  International Components for Unicode
  or "ICU" extension to SQLite to be added to the build.  

SQLITE_ENABLE_IOTRACE
  When both the SQLite core and the Command Line Interface (CLI) are both 
  compiled with this option, then the CLI provides an extra command
  named ".iotrace" that provides a low-level log of I/O activity.
  This option is experimental and may be discontinued in a future release.

SQLITE_ENABLE_MATH_FUNCTIONS
  This macro enables the built-in SQL math functions.  This option
  is automatically added to the Makefile by the configure script on unix platforms,
  unless the --disable-math option is used.
  This option is also included on Windows builds using the
  "Makefile.msc" makefile for nmake.

SQLITE_ENABLE_JSON1
  This compile-time option is a no-op.  Prior to SQLite version 3.38.0
  (2022-02-22), it was necessary to compile with this option in order
  to include the JSON SQL functions in the build.  However, beginning
  with SQLite version 3.38.0, those functions are included by default.
  Use the -DSQLITE_OMIT_JSON option to omit them.

SQLITE_ENABLE_LOCKING_STYLE
  This option enables additional logic in the OS interface layer for
  Mac OS X. The additional logic attempts to determine the type of the
  underlying filesystem and choose and alternative locking strategy
  that works correctly for that filesystem type. Five locking strategies 
  are available:

  
     POSIX locking style. This is the default locking style and the
         style used by other (non Mac OS X) Unixes. Locks are obtained and 
         released using the fcntl() system call.

     AFP locking style. This locking style is used for network file 
         systems that use the AFP (Apple Filing Protocol) protocol. Locks
         are obtained by calling the library function _AFPFSSetLock().

     Flock locking style. This is used for file-systems that do not
         support POSIX locking style. Locks are obtained and released using
         the flock() system call.

     Dot-file locking style. This locking style is used when neither
         flock nor POSIX locking styles are supported by the file system.
         Database locks are obtained by creating and entry in the file-system
         at a well-known location relative to the database file (a "dot-file")
         and relinquished by deleting the same file.

     No locking style. If none of the above can be supported, this 
         locking style is used. No database locking mechanism is used. When
         this system is used it is not safe for a single database to be
         accessed by multiple clients.
  

  Additionally, five extra VFS implementations are provided as well as the
  default. By specifying one of the extra VFS implementations 
  when calling sqlite3_open_v2(), an application may bypass the file-system
  detection logic and explicitly select one of the above locking styles. The
  five extra VFS implementations are called "unix-posix", "unix-afp",
  "unix-flock", "unix-dotfile" and "unix-none".

SQLITE_ENABLE_MEMORY_MANAGEMENT
  This option adds extra logic to SQLite that allows it to release unused
  memory upon request.  This option must be enabled in order for the
  sqlite3_release_memory() interface to work.  If this compile-time
  option is not used, the sqlite3_release_memory() interface is a 
  no-op.

SQLITE_ENABLE_MEMSYS3
  This option includes code in SQLite that implements an alternative
  memory allocator.  This alternative memory allocator is only engaged
  when the SQLITE_CONFIG_HEAP option to sqlite3_config() is used to
  supply a large chunk of memory from which all memory allocations are
  taken.
  The MEMSYS3 memory allocator uses a hybrid allocation algorithm 
  patterned after dlmalloc().   Only one of SQLITE_ENABLE_MEMSYS3 and 
  SQLITE_ENABLE_MEMSYS5 may be enabled at once.

SQLITE_ENABLE_MEMSYS5
  This option includes code in SQLite that implements an alternative
  memory allocator.  This alternative memory allocator is only engaged
  when the SQLITE_CONFIG_HEAP option to sqlite3_config() is used to
  supply a large chunk of memory from which all memory allocations are
  taken.
  The MEMSYS5 module rounds all allocations up to the next power
  of two and uses a first-fit, buddy-allocator algorithm
  that provides strong guarantees against fragmentation and breakdown
  subject to certain operating constraints.

SQLITE_ENABLE_NORMALIZE
  This option includes the sqlite3_normalized_sql() API.

SQLITE_ENABLE_NULL_TRIM
  This option enables an optimization that omits NULL columns at
  the ends of rows, for a space savings on disk.
  
  Databases generated with this option enabled are not readable
  by SQLite version 3.1.6 (2005-03-17) and earlier.  Also,
  databases generated with this option enabled are prone to
  triggering the
  e6e962d6b0f06f46
  bug in the sqlite3_blob_reopen() interface.  For those reasons,
  this optimization is disabled by default.  However, this optimization
  may be enabled by default in a future release of SQLite.

SQLITE_ENABLE_OFFSET_SQL_FUNC
  This option enables support for the sqlite_offset(X) SQL function.
  
  The sqlite_offset(X) SQL function requires a new interface on the
  B-tree storage engine, a new opcode in the virtual machine that
  runs SQL statements, and a new conditional in a critical path of the
  code generator.  To avoid that overhead in applications that do not
  need the utility of sqlite_offset(X), the function is disabled by
  default.

SQLITE_ENABLE_PREUPDATE_HOOK
  This option enables 
  several new APIs that provide callbacks
  prior to any change to a rowid table.  The callbacks can be used
  to record the state of the row before the change occurs.
  The action of the preupdate hook is similar to the
  update hook except that the callback is
  invoked before the change, not afterwards, and the preupdate
  hook interfaces are omitted unless this compile-time option is
  used.
  The preupdate hook interfaces were originally added to
  support the session extension.

SQLITE_ENABLE_QPSG
  This option causes the query planner stability guarantee (QPSG) to
  be on by default.  Normally the QPSG is off and must be activated
  at run-time using the SQLITE_DBCONFIG_ENABLE_QPSG option to the
  sqlite3_db_config() interface.

SQLITE_ENABLE_RBU
  Enable the code the implements the RBU extension.

SQLITE_ENABLE_RTREE
  This option causes SQLite to include support for the
  R*Tree index extension.

SQLITE_ENABLE_SESSION
  This option enables the session extension.

SQLITE_ENABLE_SNAPSHOT
  This option enables the code to support the sqlite3_snapshot object
  and its related interfaces:
  
   sqlite3_snapshot_get() (constructor)
   sqlite3_snapshot_free() (destructor)
   sqlite3_snapshot_open()
   sqlite3_snapshot_cmp()
   sqlite3_snapshot_recover()
  

SQLITE_ENABLE_SORTER_REFERENCES
  This option activates an optimization that reduces the memory required
  by the sorter at the cost of doing additional B-tree lookups after
  the sort has occurred.
  
  The default sorting procedure is to gather all information that will
  ultimately be output into a "record" and pass that complete record
  to the sorter.  But in some cases, for example if some of the output
  columns consists of large BLOB values, the size of the each record
  can be large, which means that the sorter has to either use more memory,
  and/or write more content to temporary storage.
  
  When SQLITE_ENABLE_SORTER_REFERENCES is enabled, the records passed to
  the sorter often contain only a ROWID value.  Such records are much
  smaller.  This means the sorter has much less "payload" to deal with and
  can run faster.  After sorting has occurred, the ROWID is used to look up 
  the output column values in the original table.  That requires another
  search into the table, and could potentially result in a slowdown.  Or,
  it might be a performance win, depending on how large the values are.
  
  Even when the SQLITE_ENABLE_SORTER_REFERENCES compile-time option is on,
  sorter references are still disabled by default.  To use sorter references,
  the application must set a sorter reference size threshold using the
  sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE) interface at start-time.
  
  Because the SQLite developers do not know whether the 
  SQLITE_ENABLE_SORTER_REFERENCES option will help or hurt performance,
  it is disabled by default at this time (2018-05-04).  It might be enabled
  by default in some future release, depending on what is learned about its
  impact on performance.

SQLITE_ENABLE_STMT_SCANSTATUS
  This option enables the sqlite3_stmt_scanstatus() interface.  The
  sqlite3_stmt_scanstatus() interface is normally omitted from the build
  because it imposes a small performance penalty, even on statements that
  do not use the feature.

SQLITE_ENABLE_STMTVTAB
  This compile-time option enables the SQLITE_STMT virtual table logic.

SQLITE_RTREE_INT_ONLY
  This compile-time option is deprecated and untested.

SQLITE_ENABLE_SQLLOG
  This option enables extra code (especially the SQLITE_CONFIG_SQLLOG
  option to sqlite3_config()) that can be used to create logs of all
  SQLite processing performed by an application.  These logs can be useful
  in doing off-line analysis of the behavior of an application, and especially
  for performance analysis.  In order for the SQLITE_ENABLE_SQLLOG option to 
  be useful, some extra code is required.  The 
  "test_sqllog.c"
  source code
  file in the SQLite source tree is a working example of the required extra
  code.  On unix and windows systems, a developer can append the text of the
  "test_sqllog.c" source code file to the end of an "sqlite3.c" amalgamation,
  recompile the application using the -DSQLITE_ENABLE_SQLLOG option, then 
  control logging using environment variables.  See the header comment on 
  the "test_sqllog.c" source file for additional detail.  

SQLITE_ENABLE_STAT2
  This option used to cause the ANALYZE command to collect
  index histogram data in the sqlite_stat2 table.  But that
  functionality was superceded by SQLITE_ENABLE_STAT3 as of
  SQLite version 3.7.9 (2011-11-01).  
  The SQLITE_ENABLE_STAT2 compile-time option
  is now a no-op.

SQLITE_ENABLE_STAT3
  This option used to cause the ANALYZE command to collect
  index histogram data in the sqlite_stat3 table.  But that
  functionality was superceded by SQLITE_ENABLE_STAT4 as of
  SQLite version 3.8.1 (2013-10-17).  
  The SQLITE_ENABLE_STAT3 compile-time option
  continued to be supported through version 3.29.0 (2019-07-10)
  but has now become a no-op.
  

SQLITE_ENABLE_STAT4
  This option adds additional logic to the ANALYZE command and to
  the query planner that can help SQLite to chose a better query plan
  under certain situations.  The ANALYZE command is enhanced to collect
  histogram data from all columns of every index and store that data
  in the sqlite_stat4 table.  The query planner will then use the
  histogram data to help it make better index choices.  The downside of
  this compile-time option is that it violates the
  query planner stability guarantee making it more difficult to ensure
  consistent performance in mass-produced applications.
  
  SQLITE_ENABLE_STAT4 is an enhancement of SQLITE_ENABLE_STAT3.  STAT3
  only recorded histogram data for the left-most column of each index
  whereas the STAT4 enhancement records histogram data from all columns
  of each index.
  The SQLITE_ENABLE_STAT3 compile-time option has become a no-op.

SQLITE_ENABLE_TREE_EXPLAIN
  This compile-time option is no longer used.

SQLITE_ENABLE_UPDATE_DELETE_LIMIT
  This option enables an optional ORDER BY and LIMIT clause on 
  UPDATE and DELETE statements.

  If this option is defined, then it must also be 
  defined when using the Lemon parser generator tool to generate a parse.c
  file. Because of this, this option may only be used when the library is built
  from source, not from the amalgamation or from the collection of
  pre-packaged C files provided for non-Unix like platforms on the website.
  

SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
  When the SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION compile-time option is
  activated, SQLite will suppress "unknown function" errors when running
  an EXPLAIN or EXPLAIN QUERY PLAN.  Instead of throwing an error,
  SQLite will insert a substitute no-op function named "unknown()".
  The substitution of "unknown()" in place of unrecognized functions
  only occurs on EXPLAIN and EXPLAIN QUERY PLAN, not on ordinary
  statements.
  
  When used in the command-line shell, the
  SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION feature allows SQL text that contains
  application-defined functions to be pasted into the shell for 
  analysis and debugging without having to create and load an
  extension that implements the application-defined functions.

SQLITE_ENABLE_UNLOCK_NOTIFY
  This option enables the sqlite3_unlock_notify() interface and
  its associated functionality.  See the documentation titled
  Using the SQLite Unlock Notification Feature for additional
  information.

SQLITE_INTROSPECTION_PRAGMAS
  This option is obsolete.  It used to enable some extra
  some extra PRAGMA statements such as
  PRAGMA function_list, PRAGMA module_list, and
  PRAGMA pragma_list, but those pragmas are now all
  enabled by default.  See SQLITE_OMIT_INTROSPECTION_PRAGMAS.

SQLITE_SOUNDEX
  This option enables the soundex() SQL function.

SQLITE_USE_ALLOCA
  If this option is enabled, then the alloca() memory allocator will be
  used in a few situations where it is appropriate.  This results in a slightly
  smaller and faster binary.  The SQLITE_USE_ALLOCA compile-time only
  works, of course, on systems that support alloca().

SQLITE_USE_FCNTL_TRACE
  This option causes SQLite to issue extra SQLITE_FCNTL_TRACE file controls
  to provide supplementary information to the VFS.  The "vfslog.c" extension
  makes use of this to provide enhanced logs of VFS activity.

SQLITE_HAVE_ZLIB
  This option causes some extensions to link against the 
  zlib compression library.
  
  This option has no effect on the SQLite core.  It is only used by extensions.
  This is option is necessary for the compression and decompression
  functions that are part of SQL Archive support in the
  command-line shell.
  
  When compiling with this option, it will normally
  be necessary to add a linker option to include the zlib library in the
  build.  Normal this option is "-lz" but might be different on different
  systems.
  
  When building with MSVC on Windows systems, one can put the zlib source
  code in the compat/zlib subdirectory of the source tree and then add
  the USE_ZLIB=1 option to the nmake command to cause the The Makefile.msc
  to automatically build and use an appropriate zlib library implementation.

YYTRACKMAXSTACKDEPTH
  This option causes the LALR(1) parser stack depth to be tracked
  and reported using the sqlite3_status(SQLITE_STATUS_PARSER_STACK,...)
  interface.  SQLite's LALR(1) parser has a fixed stack depth
  (determined at compile-time using the YYSTACKDEPTH options).
  This option can be used to help determine if an application is
  getting close to exceeding the maximum LALR(1) stack depth.



8.  Options To Disable Features Normally Turned On


SQLITE_DISABLE_LFS
  If this C-preprocessor macro is defined, large file support
  is disabled.

SQLITE_DISABLE_DIRSYNC
  If this C-preprocessor macro is defined, directory syncs
  are disabled.  SQLite typically attempts to sync the parent
  directory when a file is deleted to ensure the directory
  entries are updated immediately on disk.

SQLITE_DISABLE_FTS3_UNICODE
  If this C-preprocessor macro is defined, the unicode61 tokenizer
  in FTS3 is omitted from the build and is unavailable to 
  applications.

SQLITE_DISABLE_FTS4_DEFERRED
  If this C-preprocessor macro disables the "deferred token" optimization
  in FTS4.  The "deferred token" optimization avoids loading massive
  posting lists for terms that are in most documents of the collection
  and instead simply scans for those tokens in the document source.  FTS4
  should get exactly the same answer both with and without this optimization.

SQLITE_DISABLE_INTRINSIC
  This option disables the use of compiler-specific built-in functions
  such as __builtin_bswap32() and __builtin_add_overflow() in GCC and Clang, 
  or _byteswap_ulong() and _ReadWriteBarrier() with MSVC.  




9.  Options To Omit Features

The following options can be used to 
reduce the size of the compiled library
by omitting unused features. This is probably only useful
in embedded systems where space is especially tight, as even with all
features included the SQLite library is relatively small. Don't forget
to tell your compiler to optimize for binary size! (the -Os option if
using GCC).  Telling your compiler to optimize for size usually has
a much larger impact on library footprint than employing any of these
compile-time options.  You should also verify that 
debugging options are disabled.

The macros in this section do not require values. The following 
compilation switches all have the same effect:
-DSQLITE_OMIT_ALTERTABLE
-DSQLITE_OMIT_ALTERTABLE=1
-DSQLITE_OMIT_ALTERTABLE=0


If any of these options are defined, then the same set of SQLITE_OMIT_*
options must also be defined when using the Lemon parser generator
tool to generate the
parse.c file and when compiling the 'mkkeywordhash' tool which generates 
the keywordhash.h file.
Because of this, these options may only be used when the library is built
from canonical source, not from the amalgamation.
Some SQLITE_OMIT_* options might work, or appear to work, when used with
the amalgamation.  But this is not guaranteed.  In general, always compile
from canonical sources in order to take advantage of SQLITE_OMIT_* options.



Important Note: The SQLITE_OMIT_* options may not work with the
amalgamation.  SQLITE_OMIT_* compile-time
options usually work correctly only when SQLite is built from canonical 
source files.




Special versions of the SQLite amalgamation that do work with a
predetermined set of SQLITE_OMIT_* options can be generated.  To do so,
make a copy of the Makefile.linux-gcc makefile template in the canonical
source code distribution.  Change the name of your copy to simply "Makefile".
Then edit "Makefile" to set up appropriate compile-time options.  Then
type:
make clean; make sqlite3.c

The resulting "sqlite3.c" amalgamation code file (and its associated
header file "sqlite3.h") can then be moved to a non-unix platform
for final compilation using a native compiler.

The SQLITE_OMIT_* options are unsupported.  By this we mean that
an SQLITE_OMIT_* option that omits code from the build in the current
release might become a no-op in the next release.  Or the other way around:
an SQLITE_OMIT_* that is a no-op in the current release might cause code
to be excluded in the next release.  Also, not all SQLITE_OMIT_* options
are tested.  Some SQLITE_OMIT_* options might cause SQLite to malfunction
and/or provide incorrect answers.


Important Note:
The SQLITE_OMIT_* compile-time options are mostly unsupported.


The following are the available OMIT options:


SQLITE_OMIT_ALTERTABLE
  When this option is defined, the 
  ALTER TABLE command is not included in the 
  library. Executing an ALTER TABLE statement causes a parse error.

SQLITE_OMIT_ANALYZE
  When this option is defined, the ANALYZE command is omitted from
  the build.

SQLITE_OMIT_ATTACH
  When this option is defined, the ATTACH and DETACH commands are
  omitted from the build.

SQLITE_OMIT_AUTHORIZATION
  Defining this option omits the authorization callback feature from the
  library. The sqlite3_set_authorizer() API function is not present
  in the library.

SQLITE_OMIT_AUTOINCREMENT
  This option is omits the AUTOINCREMENT feature. 
  When this is macro is defined, columns declared as 
  "INTEGER PRIMARY KEY AUTOINCREMENT"
  behave in the same way as columns declared as "INTEGER PRIMARY KEY" when a 
  NULL is inserted. The sqlite_sequence system table is neither created, nor
  respected if it already exists.

SQLITE_OMIT_AUTOINIT
  For backwards compatibility with older versions of SQLite that lack
  the sqlite3_initialize() interface, the sqlite3_initialize() interface
  is called automatically upon entry to certain key interfaces such as
  sqlite3_open(), sqlite3_vfs_register(), and sqlite3_mprintf().
  The overhead of invoking sqlite3_initialize() automatically in this
  way may be omitted by building SQLite with the SQLITE_OMIT_AUTOINIT
  C-preprocessor macro.  When built using SQLITE_OMIT_AUTOINIT, SQLite
  will not automatically initialize itself and the application is required
  to invoke sqlite3_initialize() directly prior to beginning use of the
  SQLite library.

SQLITE_OMIT_AUTOMATIC_INDEX
  This option is used to omit the 
  automatic indexing functionality.
  See also: SQLITE_DEFAULT_AUTOMATIC_INDEX.

SQLITE_OMIT_AUTORESET
  By default, the sqlite3_step() interface will automatically invoke
  sqlite3_reset() to reset the prepared statement if necessary.  This
  compile-time option changes that behavior so that sqlite3_step() will
  return SQLITE_MISUSE if it called again after returning anything other
  than SQLITE_ROW, SQLITE_BUSY, or SQLITE_LOCKED unless there was an
  intervening call to sqlite3_reset().

  In SQLite version 3.6.23.1 (2010-03-26)
  and earlier, sqlite3_step() used to always
  return SQLITE_MISUSE if it was invoked again after returning anything
  other than SQLITE_ROW without an intervening call to sqlite3_reset().
  This caused problems on some poorly written smartphone applications which
  did not correctly handle the SQLITE_LOCKED and SQLITE_BUSY error 
  returns.  Rather than fix the many defective smartphone applications, 
  the behavior of SQLite was changed in 3.6.23.2 to automatically reset
  the prepared statement.  But that changed caused issues in other 
  improperly implemented applications that were actually looking
  for an SQLITE_MISUSE return to terminate their query loops.  (Anytime
  an application gets an SQLITE_MISUSE error code from SQLite, that means the
  application is misusing the SQLite interface and is thus incorrectly
  implemented.)  The SQLITE_OMIT_AUTORESET interface was added to SQLite
  version 3.7.5 (2011-02-01) in an effort to get all of the (broken)
  applications to work again without having to actually fix the applications.

SQLITE_OMIT_AUTOVACUUM
  If this option is defined, the library cannot create or write to 
  databases that support auto_vacuum.
  Executing a PRAGMA auto_vacuum statement is not an error
  (since unknown PRAGMAs are silently ignored), but does not return a value
  or modify the auto-vacuum flag in the database file. If a database that
  supports auto-vacuum is opened by a library compiled with this option, it
  is automatically opened in read-only mode.

SQLITE_OMIT_BETWEEN_OPTIMIZATION
  This option disables the use of indices with WHERE clause terms
  that employ the BETWEEN operator.

SQLITE_OMIT_BLOB_LITERAL
  When this option is defined, it is not possible to specify a blob in
  an SQL statement using the X'ABCD' syntax.

SQLITE_OMIT_BTREECOUNT
  This option is no longer used for anything.  It is a no-op.

SQLITE_OMIT_BUILTIN_TEST
  This compile-time option has been renamed to SQLITE_UNTESTABLE.

SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA
  This compile-time option disables the PRAGMA case_sensitive_like
  command.

SQLITE_OMIT_CAST
  This option causes SQLite to omit support for the CAST operator.

SQLITE_OMIT_CHECK
  This option causes SQLite to omit support for CHECK constraints.
  The parser will still accept CHECK constraints in SQL statements,
  they will just not be enforced.

SQLITE_OMIT_COMPILEOPTION_DIAGS
  This option is used to omit the compile-time option diagnostics available
  in SQLite, including the sqlite3_compileoption_used() and
  sqlite3_compileoption_get() C/C++ functions, the
  sqlite_compileoption_used() and sqlite_compileoption_get() SQL functions,
  and the compile_options pragma.

SQLITE_OMIT_COMPLETE
  This option causes the sqlite3_complete() and sqlite3_complete16()
  interfaces to be omitted.

SQLITE_OMIT_COMPOUND_SELECT
  This option is used to omit the compound SELECT functionality. 
  SELECT statements that use the 
  UNION, UNION ALL, INTERSECT or EXCEPT compound SELECT operators will 
  cause a parse error.

  An INSERT statement with multiple values in the VALUES clause is
  implemented internally as a compound SELECT.  Hence, this option also
  disables the ability to insert more than a single row using an
  INSERT INTO ... VALUES ... statement.

SQLITE_OMIT_CTE
  This option causes support for common table expressions to be omitted.

SQLITE_OMIT_DATETIME_FUNCS
  If this option is defined, SQLite's built-in date and time manipulation
  functions are omitted. Specifically, the SQL functions julianday(), date(),
  time(), datetime() and strftime() are not available. The default column
  values CURRENT_TIME, CURRENT_DATE and CURRENT_TIMESTAMP are still available.

SQLITE_OMIT_DECLTYPE
  This option causes SQLite to omit support for the
  sqlite3_column_decltype() and sqlite3_column_decltype16()
  interfaces.

SQLITE_OMIT_DEPRECATED
  This option causes SQLite to omit support for interfaces
  marked as deprecated.  This includes 
  sqlite3_aggregate_count(),
  sqlite3_expired(),
  sqlite3_transfer_bindings(),
  sqlite3_global_recover(),
  sqlite3_thread_cleanup() and
  sqlite3_memory_alarm() interfaces and
  PRAGMA statements PRAGMA count_changes,
  PRAGMA data_store_directory,
  PRAGMA default_cache_size,
  PRAGMA empty_result_callbacks,
  PRAGMA full_column_names,
  PRAGMA short_column_names, and
  PRAGMA temp_store_directory.

SQLITE_OMIT_DESERIALIZE
  This option causes the
  sqlite3_serialize() and sqlite3_deserialize()
  interfaces to be omitted from the build.

SQLITE_OMIT_DISKIO
  This option omits all support for writing to the disk and forces
  databases to exist in memory only.  This option has not been 
  maintained and probably does not work with newer versions of SQLite.

SQLITE_OMIT_EXPLAIN
  Defining this option causes the EXPLAIN command to be omitted from the
  library. Attempting to execute an EXPLAIN statement will cause a parse
  error.

SQLITE_OMIT_FLAG_PRAGMAS
  This option omits support for a subset of PRAGMA commands that
  query and set boolean properties.

SQLITE_OMIT_FLOATING_POINT
  This option is used to omit floating-point number support from the SQLite
  library. When specified, specifying a floating point number as a literal 
  (i.e. "1.01") results in a parse error.

  In the future, this option may also disable other floating point 
  functionality, for example the sqlite3_result_double(), 
  sqlite3_bind_double(), sqlite3_value_double() and
  sqlite3_column_double() API functions.
  

SQLITE_OMIT_FOREIGN_KEY
  If this option is defined, then foreign key constraint syntax is
  not recognized.

SQLITE_OMIT_GENERATED_COLUMNS
  If this option is defined, then generated column syntax is
  not recognized.

SQLITE_OMIT_GET_TABLE
  This option causes support for sqlite3_get_table() and
  sqlite3_free_table() to be omitted.

SQLITE_OMIT_HEX_INTEGER
  This option omits support for hexadecimal integer literals.

SQLITE_OMIT_INCRBLOB
  This option causes support for incremental BLOB I/O
  to be omitted.

SQLITE_OMIT_INTEGRITY_CHECK
  This option omits support for the integrity_check pragma.

SQLITE_OMIT_INTROSPECTION_PRAGMAS
  This option omits support for
  PRAGMA function_list, PRAGMA module_list, and
  PRAGMA pragma_list.

SQLITE_OMIT_JSON
  This option omits the JSON SQL functions from the build.

SQLITE_OMIT_LIKE_OPTIMIZATION
  This option disables the ability of SQLite to use indices to help
  resolve LIKE and GLOB operators in a WHERE clause.

SQLITE_OMIT_LOAD_EXTENSION
  This option omits the entire extension loading mechanism from
  SQLite, including sqlite3_enable_load_extension() and
  sqlite3_load_extension() interfaces.

SQLITE_OMIT_LOCALTIME
  This option omits the "localtime" modifier from the date and time
  functions.  This option is sometimes useful when trying to compile
  the date and time functions on a platform that does not support the
  concept of local time.

SQLITE_OMIT_LOOKASIDE
  This option omits the lookaside memory allocator.

SQLITE_OMIT_MEMORYDB
  When this is defined, the library does not respect the special database
  name ":memory:" (normally used to create an in-memory database). If 
  ":memory:" is passed to sqlite3_open(), sqlite3_open16(), or
  sqlite3_open_v2(), a file with this name will be 
  opened or created.

SQLITE_OMIT_OR_OPTIMIZATION
  This option disables the ability of SQLite to use an index together
  with terms of a WHERE clause connected by the OR operator.

SQLITE_OMIT_PAGER_PRAGMAS
  Defining this option omits pragmas related to the pager subsystem from 
  the build.

SQLITE_OMIT_PRAGMA
  This option is used to omit the PRAGMA command
  from the library. Note that it is useful to define the macros that omit
  specific pragmas in addition to this, as they may also remove supporting code
  in other sub-systems. This macro removes the PRAGMA command only.

SQLITE_OMIT_PROGRESS_CALLBACK
  This option may be defined to omit the capability to issue "progress" 
  callbacks during long-running SQL statements. The 
  sqlite3_progress_handler()
  API function is not present in the library.

SQLITE_OMIT_QUICKBALANCE
  This option omits an alternative, faster B-Tree balancing routine.
  Using this option makes SQLite slightly smaller at the expense of
  making it run slightly slower.

SQLITE_OMIT_REINDEX
  When this option is defined, the REINDEX
  command is not included in the library.
  Executing a REINDEX statement causes 
  a parse error.

SQLITE_OMIT_SCHEMA_PRAGMAS
  Defining this option omits pragmas for querying the database schema from 
  the build.

SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
  Defining this option omits pragmas for querying and modifying the 
  database schema version and user version from the build. Specifically, the 
  schema_version and user_version PRAGMAs are omitted.

SQLITE_OMIT_SHARED_CACHE
  This option builds SQLite without support for shared cache mode.
  The sqlite3_enable_shared_cache() is omitted along with a fair
  amount of logic within the B-Tree subsystem associated with shared
  cache management.

  This compile-time option is recommended most applications as it
  results in improved performance and reduced library footprint.

SQLITE_OMIT_SUBQUERY
  If defined, support for sub-selects and the IN() operator are omitted.

SQLITE_OMIT_TCL_VARIABLE
  If this macro is defined, then the special "$" syntax
  used to automatically bind SQL variables to TCL variables is omitted.

SQLITE_OMIT_TEMPDB
  This option omits support for TEMP or TEMPORARY tables.

SQLITE_OMIT_TRACE
  This option omits support for the sqlite3_profile() and
  sqlite3_trace() interfaces and their associated logic.

SQLITE_OMIT_TRIGGER
  Defining this option omits support for TRIGGER objects. Neither the 
  CREATE TRIGGER or DROP TRIGGER
  commands are available in this case, and attempting to execute
  either will result in a parse error.
  This option also disables enforcement of foreign key constraints,
  since the code that implements triggers and which is omitted by this
  option is also used to implement foreign key actions.

SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  A default build of SQLite, if a DELETE statement has no WHERE clause
  and operates on a table with no triggers, an optimization occurs that
  causes the DELETE to occur by dropping and recreating the table.  
  Dropping and recreating a table is usually much faster than deleting
  the table content row by row.  This is the "truncate optimization".

SQLITE_OMIT_UTF16
  This macro is used to omit support for UTF16 text encoding. When this is
  defined all API functions that return or accept UTF16 encoded text are
  unavailable. These functions can be identified by the fact that they end
  with '16', for example sqlite3_prepare16(), sqlite3_column_text16() and
  sqlite3_bind_text16().

SQLITE_OMIT_VACUUM
  When this option is defined, the VACUUM
  command is not included in the library.
  Executing a VACUUM statement causes 
  a parse error.

SQLITE_OMIT_VIEW
  Defining this option omits support for VIEW objects. Neither the 
  CREATE VIEW nor the DROP VIEW
  commands are available in this case, and
  attempting to execute either will result in a parse error.

  WARNING: If this macro is defined, it will not be possible to open a database
  for which the schema contains VIEW objects. 

SQLITE_OMIT_VIRTUALTABLE
  This option omits support for the Virtual Table
  mechanism in SQLite.

SQLITE_OMIT_WAL
  This option omits the "write-ahead log" (a.k.a. "WAL") capability.

SQLITE_OMIT_WINDOWFUNC
  This option omits window functions from the build.

SQLITE_OMIT_WSD
  This option builds a version of the SQLite library that contains no
  Writable Static Data (WSD).  WSD is global variables and/or static
  variables.  Some platforms do not support WSD, and this option is necessary
  in order for SQLite to work those platforms.  

  Unlike other OMIT options which make the SQLite library smaller,
  this option actually increases the size of SQLite and makes it run
  a little slower.  Only use this option if SQLite is being built for an
  embedded target that does not support WSD.

SQLITE_OMIT_XFER_OPT
  This option omits support for optimizations that help statements
  of the form "INSERT INTO ... SELECT ..." run faster.

SQLITE_UNTESTABLE
  A standard SQLite build includes a small amount of logic associated
  with sqlite3_test_control() to exercise
  parts of the SQLite core that are otherwise difficult to validate.
  This compile-time option omits that extra testing logic.  This
  compile-time option was called "SQLITE_OMIT_BUILTIN_TEST" prior
  to SQLite version 3.16.0 (2017-01-02).  The name was changed
  to better describe the implications of using it.
  
  Setting this compile-time option prevents SQLite from being fully
  testable.  Branch test coverage drops from 100% down to about 95%.
  
  SQLite developers follow the NASA principle of
  "fly what you test and test what you fly".  This principle is violated
  if this option is enabled for delivery but disabled for testing.
  But if this option is enabled during testing, not all branches are 
  reachable.  Therefore, the use of this compile-time option is discouraged.

SQLITE_ZERO_MALLOC
  This option omits both the default memory allocator and the
  debugging memory allocator from the build and substitutes a stub
  memory allocator that always fails.  SQLite will not run with this
  stub memory allocator since it will be unable to allocate memory.  But
  this stub can be replaced at start-time using
  sqlite3_config(SQLITE_CONFIG_MALLOC,...) or
  sqlite3_config(SQLITE_CONFIG_HEAP,...).
  So the net effect of this compile-time option is that it allows SQLite
  to be compiled and linked against a system library that does not support
  malloc(), free(), and/or realloc().


10.  Analysis and Debugging Options

SQLITE_DEBUG
  The SQLite source code contains literally thousands of assert() statements
  used to verify internal assumptions and subroutine preconditions and
  postconditions.  These assert() statements are normally turned off
  (they generate no code) since turning them on makes SQLite run approximately
  three times slower.  But for testing and analysis, it is useful to turn
  the assert() statements on.  The SQLITE_DEBUG compile-time option does this.
  SQLITE_DEBUG also enables some other debugging features, such as
  special PRAGMA statements that turn on tracing and listing features
  used for troubleshooting and analysis of the VDBE and code generator.

SQLITE_MEMDEBUG
  The SQLITE_MEMDEBUG option causes an instrumented 
  debugging memory allocator
  to be used as the default memory allocator within SQLite.  The
  instrumented memory allocator checks for misuse of dynamically allocated
  memory.  Examples of misuse include using memory after it is freed,
  writing off the ends of a memory allocation, freeing memory not previously
  obtained from the memory allocator, or failing to initialize newly
  allocated memory.


11.  Windows-Specific Options

SQLITE_WIN32_HEAP_CREATE
  This option forces the Win32 native memory allocator, when enabled, to
  create a private heap to hold all memory allocations.

SQLITE_WIN32_MALLOC_VALIDATE
  This option forces the Win32 native memory allocator, when enabled, to
  make strategic calls into the HeapValidate() function if assert() is also
  enabled.


12. Compiler Linkage and Calling Convention Control

The following macros specify interface details
for certain kinds of SQLite builds.  The Makefiles will normally
handle setting these macros automatically.  Application developers should
not need to worry with these macros.  The following documentation about these 
macros is included for completeness.


SQLITE_API
  This macro identifies an externally visible interface for SQLite.
  This macro is sometimes set to "extern".  But the definition is
  compiler-specific.

SQLITE_APICALL
  This macro identifies the calling convention used by public interface
  routines in SQLite which accept a fixed number of arguments.
  This macro is normally defined to be nothing,
  though on Windows builds it can sometimes be set to "__cdecl" or "__stdcall".
  The "__cdecl" setting is the default, but "__stdcall" is used when SQLite
  is intended to be compiled as a Windows system library.
  
  A single function declaration should contain no more than one of
  the following:  SQLITE_APICALL, SQLITE_CDECL, or SQLITE_SYSAPI.

SQLITE_CALLBACK
  This macro specifies the calling convention used with callback pointers
  in SQLite.  This macro is normally defined to be nothing, though on Windows
  builds it can sometimes be set to "__cdecl" or "__stdcall".  The
  "__cdecl" setting is the default, but "__stdcall" is used when SQLite
  is intended to be compiled as a Windows system library.

SQLITE_CDECL
  This macro specifies the calling convention used by varargs interface
  routines in SQLite.  This macro is normally defined to be nothing,
  though on Windows builds it can sometimes be set to "__cdecl".  This
  macro is used on varargs routines and so cannot be set to "__stdcall"
  since the __stdcall calling convention does not support varargs functions.
  
  A single function declaration should contain no more than one of
  the following:  SQLITE_APICALL, SQLITE_CDECL, or SQLITE_SYSAPI.

SQLITE_EXTERN
  This macro specifies linkage for public interface variables in SQLite.
  It should normally be allowed to default to "extern".

SQLITE_STDCALL
  This macro is no longer used and is now deprecated.

SQLITE_SYSAPI
  This macro identifies the calling convention used by operating system
  interfaces for the target platform for an SQLite build.
  This macro is normally defined to be nothing,
  though on Windows builds it can sometimes be set to "__stdcall".
  
  A single function declaration should contain no more than one of
  the following:  SQLITE_APICALL, SQLITE_CDECL, or SQLITE_SYSAPI.

SQLITE_TCLAPI
  This macro specifies the calling convention used by the 
  TCL library interface routines.
  This macro is not used by the SQLite core, but only by the TCL Interface
  and TCL test suite.
  This macro is normally defined to be nothing,
  though on Windows builds it can sometimes be set to "__cdecl".  This
  macro is used on TCL library interface routines which are always compiled
  as __cdecl, even on platforms that prefer to use __stdcall, so this
  macro should not be set to __stdcall unless the platform has a custom
  TCL library build that supports __stdcall.
  
  This macro may not be used in combination with any of SQLITE_APICALL,
  SQLITE_CALLBACK, SQLITE_CDECL or SQLITE_SYSAPI.

This page last modified on  2022-11-07 14:28:05 UTC


c2: Syntax Diagrams For SQLite
c5: syntaxdiagrams.html
c4:
Syntax Diagrams For SQLite

aggregate-function-invocation:



References:&nbsp;&nbsp; expr&nbsp;&nbsp; filter-clause
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_expr.html#booleanexpr


alter-table-stmt:



Used by:&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; column-def
See also:&nbsp;&nbsp; lang_altertable.html


analyze-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_analyze.html


attach-stmt:



Used by:&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_attach.html


begin-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_transaction.html


column-constraint:



Used by:&nbsp;&nbsp; column-def
References:&nbsp;&nbsp; conflict-clause&nbsp;&nbsp; expr&nbsp;&nbsp; foreign-key-clause&nbsp;&nbsp; literal-value&nbsp;&nbsp; signed-number
See also:&nbsp;&nbsp; gencol.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtable.html#tablecoldef


column-def:



Used by:&nbsp;&nbsp; alter-table-stmt&nbsp;&nbsp; create-table-stmt
References:&nbsp;&nbsp; column-constraint&nbsp;&nbsp; type-name
See also:&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_altertable.html#altertabaddcol&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtable.html#tablecoldef


column-name-list:



Used by:&nbsp;&nbsp; update-stmt&nbsp;&nbsp; update-stmt-limited&nbsp;&nbsp; upsert-clause
See also:&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html


comment-syntax:



See also:&nbsp;&nbsp; lang_comment.html


commit-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_transaction.html


common-table-expression:



Used by:&nbsp;&nbsp; compound-select-stmt&nbsp;&nbsp; delete-stmt&nbsp;&nbsp; delete-stmt-limited&nbsp;&nbsp; factored-select-stmt&nbsp;&nbsp; insert-stmt&nbsp;&nbsp; select-stmt&nbsp;&nbsp; simple-select-stmt&nbsp;&nbsp; update-stmt&nbsp;&nbsp; update-stmt-limited
References:&nbsp;&nbsp; select-stmt
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


compound-operator:



Used by:&nbsp;&nbsp; factored-select-stmt&nbsp;&nbsp; select-stmt
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


compound-select-stmt:



References:&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; expr&nbsp;&nbsp; ordering-term&nbsp;&nbsp; select-core
See also:&nbsp;&nbsp; lang_select.html#compound


conflict-clause:



Used by:&nbsp;&nbsp; column-constraint&nbsp;&nbsp; table-constraint
See also:&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_conflict.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtable.html#notnullconst


create-index-stmt:



Used by:&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; expr&nbsp;&nbsp; indexed-column
See also:&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; partialindex.html


create-table-stmt:



Used by:&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; column-def&nbsp;&nbsp; select-stmt&nbsp;&nbsp; table-constraint&nbsp;&nbsp; table-options
See also:&nbsp;&nbsp; lang_createtable.html


create-trigger-stmt:



Used by:&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; delete-stmt&nbsp;&nbsp; expr&nbsp;&nbsp; insert-stmt&nbsp;&nbsp; select-stmt&nbsp;&nbsp; update-stmt
See also:&nbsp;&nbsp; lang_createtrigger.html


create-view-stmt:



Used by:&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; select-stmt
See also:&nbsp;&nbsp; lang_createview.html


create-virtual-table-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_createvtab.html


cte-table-name:



Used by:&nbsp;&nbsp; recursive-cte&nbsp;&nbsp; with-clause
See also:&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; lang_with.html#recursivecte


delete-stmt:



Used by:&nbsp;&nbsp; create-trigger-stmt&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; expr&nbsp;&nbsp; qualified-table-name&nbsp;&nbsp; returning-clause
See also:&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_delete.html


delete-stmt-limited:



Used by:&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; expr&nbsp;&nbsp; ordering-term&nbsp;&nbsp; qualified-table-name&nbsp;&nbsp; returning-clause
See also:&nbsp;&nbsp; lang_delete.html


detach-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_detach.html


drop-index-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_dropindex.html


drop-table-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_droptable.html


drop-trigger-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_droptrigger.html


drop-view-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_dropview.html


expr:



Used by:&nbsp;&nbsp; aggregate-function-invocation&nbsp;&nbsp; attach-stmt&nbsp;&nbsp; column-constraint&nbsp;&nbsp; compound-select-stmt&nbsp;&nbsp; create-index-stmt&nbsp;&nbsp; create-trigger-stmt&nbsp;&nbsp; delete-stmt&nbsp;&nbsp; delete-stmt-limited&nbsp;&nbsp; factored-select-stmt&nbsp;&nbsp; filter-clause&nbsp;&nbsp; frame-spec&nbsp;&nbsp; indexed-column&nbsp;&nbsp; insert-stmt&nbsp;&nbsp; join-constraint&nbsp;&nbsp; ordering-term&nbsp;&nbsp; over-clause&nbsp;&nbsp; result-column&nbsp;&nbsp; returning-clause&nbsp;&nbsp; select-core&nbsp;&nbsp; select-stmt&nbsp;&nbsp; simple-function-invocation&nbsp;&nbsp; simple-select-stmt&nbsp;&nbsp; table-constraint&nbsp;&nbsp; table-or-subquery&nbsp;&nbsp; update-stmt&nbsp;&nbsp; update-stmt-limited&nbsp;&nbsp; upsert-clause&nbsp;&nbsp; window-defn&nbsp;&nbsp; window-function-invocation
References:&nbsp;&nbsp; filter-clause&nbsp;&nbsp; literal-value&nbsp;&nbsp; over-clause&nbsp;&nbsp; raise-function&nbsp;&nbsp; select-stmt&nbsp;&nbsp; type-name
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


factored-select-stmt:



References:&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; compound-operator&nbsp;&nbsp; expr&nbsp;&nbsp; ordering-term&nbsp;&nbsp; select-core
See also:&nbsp;&nbsp; lang_select.html


filter-clause:



Used by:&nbsp;&nbsp; aggregate-function-invocation&nbsp;&nbsp; expr&nbsp;&nbsp; window-function-invocation
References:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


foreign-key-clause:



Used by:&nbsp;&nbsp; column-constraint&nbsp;&nbsp; table-constraint
See also:&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_altertable.html#altertabaddcol&nbsp;&nbsp; lang_createtable.html


frame-spec:



Used by:&nbsp;&nbsp; over-clause&nbsp;&nbsp; window-defn
References:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


indexed-column:



Used by:&nbsp;&nbsp; create-index-stmt&nbsp;&nbsp; table-constraint&nbsp;&nbsp; upsert-clause
References:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtable.html#primkeyconst&nbsp;&nbsp; lang_createtable.html#uniqueconst&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; partialindex.html


insert-stmt:



Used by:&nbsp;&nbsp; create-trigger-stmt&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; expr&nbsp;&nbsp; returning-clause&nbsp;&nbsp; select-stmt&nbsp;&nbsp; upsert-clause
See also:&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_insert.html


join-clause:



Used by:&nbsp;&nbsp; select-core&nbsp;&nbsp; select-stmt&nbsp;&nbsp; table-or-subquery&nbsp;&nbsp; update-stmt&nbsp;&nbsp; update-stmt-limited
References:&nbsp;&nbsp; join-constraint&nbsp;&nbsp; join-operator&nbsp;&nbsp; table-or-subquery
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


join-constraint:



Used by:&nbsp;&nbsp; join-clause
References:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#fromclause&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


join-operator:



Used by:&nbsp;&nbsp; join-clause
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#fromclause&nbsp;&nbsp; lang_select.html#nonstd&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


literal-value:



Used by:&nbsp;&nbsp; column-constraint&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


numeric-literal:



See also:&nbsp;&nbsp; lang_expr.html#litvalue


ordering-term:



Used by:&nbsp;&nbsp; compound-select-stmt&nbsp;&nbsp; delete-stmt-limited&nbsp;&nbsp; factored-select-stmt&nbsp;&nbsp; over-clause&nbsp;&nbsp; select-stmt&nbsp;&nbsp; simple-select-stmt&nbsp;&nbsp; update-stmt-limited&nbsp;&nbsp; window-defn
References:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


over-clause:



Used by:&nbsp;&nbsp; expr
References:&nbsp;&nbsp; expr&nbsp;&nbsp; frame-spec&nbsp;&nbsp; ordering-term
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


pragma-stmt:



Used by:&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; pragma-value
See also:&nbsp;&nbsp; pragma.html#syntax


pragma-value:



Used by:&nbsp;&nbsp; pragma-stmt
References:&nbsp;&nbsp; signed-number
See also:&nbsp;&nbsp; pragma.html#syntax


qualified-table-name:



Used by:&nbsp;&nbsp; delete-stmt&nbsp;&nbsp; delete-stmt-limited&nbsp;&nbsp; update-stmt&nbsp;&nbsp; update-stmt-limited
See also:&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_indexedby.html&nbsp;&nbsp; lang_update.html


raise-function:



Used by:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createtrigger.html#raise&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


recursive-cte:



References:&nbsp;&nbsp; cte-table-name
See also:&nbsp;&nbsp; lang_with.html#recursivecte


reindex-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_reindex.html


release-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_savepoint.html


result-column:



Used by:&nbsp;&nbsp; select-core&nbsp;&nbsp; select-stmt
References:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


returning-clause:



Used by:&nbsp;&nbsp; delete-stmt&nbsp;&nbsp; delete-stmt-limited&nbsp;&nbsp; insert-stmt&nbsp;&nbsp; update-stmt&nbsp;&nbsp; update-stmt-limited
References:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_update.html


rollback-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_savepoint.html&nbsp;&nbsp; lang_transaction.html


savepoint-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_savepoint.html


select-core:



Used by:&nbsp;&nbsp; compound-select-stmt&nbsp;&nbsp; factored-select-stmt&nbsp;&nbsp; simple-select-stmt
References:&nbsp;&nbsp; expr&nbsp;&nbsp; join-clause&nbsp;&nbsp; result-column&nbsp;&nbsp; table-or-subquery&nbsp;&nbsp; window-defn
See also:&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect


select-stmt:



Used by:&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; create-table-stmt&nbsp;&nbsp; create-trigger-stmt&nbsp;&nbsp; create-view-stmt&nbsp;&nbsp; expr&nbsp;&nbsp; insert-stmt&nbsp;&nbsp; sql-stmt&nbsp;&nbsp; table-or-subquery&nbsp;&nbsp; with-clause
References:&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; compound-operator&nbsp;&nbsp; expr&nbsp;&nbsp; join-clause&nbsp;&nbsp; ordering-term&nbsp;&nbsp; result-column&nbsp;&nbsp; table-or-subquery&nbsp;&nbsp; window-defn
See also:&nbsp;&nbsp; changes.html#version_3_35_3&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; lang_with.html#recursivecte&nbsp;&nbsp; partialindex.html&nbsp;&nbsp; releaselog/3_35_3.html&nbsp;&nbsp; releaselog/3_35_4.html&nbsp;&nbsp; releaselog/3_35_5.html


signed-number:



Used by:&nbsp;&nbsp; column-constraint&nbsp;&nbsp; pragma-value&nbsp;&nbsp; type-name
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html&nbsp;&nbsp; pragma.html#syntax


simple-function-invocation:



References:&nbsp;&nbsp; expr
See also:&nbsp;&nbsp; lang_expr.html#booleanexpr


simple-select-stmt:



References:&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; expr&nbsp;&nbsp; ordering-term&nbsp;&nbsp; select-core
See also:&nbsp;&nbsp; lang_select.html#simpleselect


sql-stmt:



Used by:&nbsp;&nbsp; sql-stmt-list
References:&nbsp;&nbsp; alter-table-stmt&nbsp;&nbsp; analyze-stmt&nbsp;&nbsp; attach-stmt&nbsp;&nbsp; begin-stmt&nbsp;&nbsp; commit-stmt&nbsp;&nbsp; create-index-stmt&nbsp;&nbsp; create-table-stmt&nbsp;&nbsp; create-trigger-stmt&nbsp;&nbsp; create-view-stmt&nbsp;&nbsp; create-virtual-table-stmt&nbsp;&nbsp; delete-stmt&nbsp;&nbsp; delete-stmt-limited&nbsp;&nbsp; detach-stmt&nbsp;&nbsp; drop-index-stmt&nbsp;&nbsp; drop-table-stmt&nbsp;&nbsp; drop-trigger-stmt&nbsp;&nbsp; drop-view-stmt&nbsp;&nbsp; insert-stmt&nbsp;&nbsp; pragma-stmt&nbsp;&nbsp; reindex-stmt&nbsp;&nbsp; release-stmt&nbsp;&nbsp; rollback-stmt&nbsp;&nbsp; savepoint-stmt&nbsp;&nbsp; select-stmt&nbsp;&nbsp; update-stmt&nbsp;&nbsp; update-stmt-limited&nbsp;&nbsp; vacuum-stmt
See also:&nbsp;&nbsp; lang.html&nbsp;&nbsp; lang_explain.html


sql-stmt-list:



References:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang.html


table-constraint:



Used by:&nbsp;&nbsp; create-table-stmt
References:&nbsp;&nbsp; conflict-clause&nbsp;&nbsp; expr&nbsp;&nbsp; foreign-key-clause&nbsp;&nbsp; indexed-column
See also:&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtable.html#primkeyconst&nbsp;&nbsp; lang_createtable.html#tablecoldef&nbsp;&nbsp; lang_createtable.html#uniqueconst


table-options:



Used by:&nbsp;&nbsp; create-table-stmt
See also:&nbsp;&nbsp; lang_createtable.html


table-or-subquery:



Used by:&nbsp;&nbsp; join-clause&nbsp;&nbsp; select-core&nbsp;&nbsp; select-stmt&nbsp;&nbsp; update-stmt&nbsp;&nbsp; update-stmt-limited
References:&nbsp;&nbsp; expr&nbsp;&nbsp; join-clause&nbsp;&nbsp; select-stmt
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


type-name:



Used by:&nbsp;&nbsp; column-def&nbsp;&nbsp; expr
References:&nbsp;&nbsp; signed-number
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


update-stmt:



Used by:&nbsp;&nbsp; create-trigger-stmt&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; column-name-list&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; expr&nbsp;&nbsp; join-clause&nbsp;&nbsp; qualified-table-name&nbsp;&nbsp; returning-clause&nbsp;&nbsp; table-or-subquery
See also:&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_update.html


update-stmt-limited:



Used by:&nbsp;&nbsp; sql-stmt
References:&nbsp;&nbsp; column-name-list&nbsp;&nbsp; common-table-expression&nbsp;&nbsp; expr&nbsp;&nbsp; join-clause&nbsp;&nbsp; ordering-term&nbsp;&nbsp; qualified-table-name&nbsp;&nbsp; returning-clause&nbsp;&nbsp; table-or-subquery
See also:&nbsp;&nbsp; lang_update.html#upfrom


upsert-clause:



Used by:&nbsp;&nbsp; insert-stmt
References:&nbsp;&nbsp; column-name-list&nbsp;&nbsp; expr&nbsp;&nbsp; indexed-column
See also:&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_upsert.html


vacuum-stmt:



Used by:&nbsp;&nbsp; sql-stmt
See also:&nbsp;&nbsp; lang_vacuum.html


window-defn:



Used by:&nbsp;&nbsp; select-core&nbsp;&nbsp; select-stmt&nbsp;&nbsp; window-function-invocation
References:&nbsp;&nbsp; expr&nbsp;&nbsp; frame-spec&nbsp;&nbsp; ordering-term
See also:&nbsp;&nbsp; lang_aggfunc.html&nbsp;&nbsp; lang_altertable.html&nbsp;&nbsp; lang_attach.html&nbsp;&nbsp; lang_createindex.html&nbsp;&nbsp; lang_createtable.html&nbsp;&nbsp; lang_createtrigger.html&nbsp;&nbsp; lang_createview.html&nbsp;&nbsp; lang_delete.html&nbsp;&nbsp; lang_expr.html&nbsp;&nbsp; lang_insert.html&nbsp;&nbsp; lang_returning.html&nbsp;&nbsp; lang_select.html&nbsp;&nbsp; lang_select.html#compound&nbsp;&nbsp; lang_select.html#simpleselect&nbsp;&nbsp; lang_update.html&nbsp;&nbsp; lang_upsert.html&nbsp;&nbsp; lang_with.html&nbsp;&nbsp; partialindex.html


window-function-invocation:



References:&nbsp;&nbsp; expr&nbsp;&nbsp; filter-clause&nbsp;&nbsp; window-defn
See also:&nbsp;&nbsp; lang_expr.html#booleanexpr


with-clause:



References:&nbsp;&nbsp; cte-table-name&nbsp;&nbsp; select-stmt
See also:&nbsp;&nbsp; lang_with.html


This page last modified on  2020-10-01 18:23:33 UTC


c2: How SQLite Is Tested
c5: testing.html
c4:
1. Introduction

The reliability and robustness of SQLite is achieved in part
by thorough and careful testing.

As of version 3.39.0 (2022-06-25),
the SQLite library consists of approximately
151.3 KSLOC of C code.
(KSLOC means thousands of "Source Lines Of Code" or, in other words,
lines of code excluding blank lines and comments.)
By comparison, the project has
608 times as much
test code and test scripts - 
92038.3 KSLOC.

1.1. Executive Summary


 Four independently developed test harnesses
 100% branch test coverage in an as-deployed configuration
 Millions and millions of test cases
 Out-of-memory tests
 I/O error tests
 Crash and power loss tests
 Fuzz tests
 Boundary value tests
 Disabled optimization tests
 Regression tests
 Malformed database tests
 Extensive use of assert() and run-time checks
 Valgrind analysis
 Undefined behavior checks
 Checklists




2. Test Harnesses

There are four independent test harnesses used for testing the 
core SQLite library.
Each test harness is designed, maintained, and managed separately
from the others.






The TCL Tests are the original tests for SQLite.  
They are contained in the same source tree as the
SQLite core and like the SQLite core are in the public domain.  The
TCL tests are the primary tests used during development.
The TCL tests are written using the 
TCL scripting language.
The TCL test harness itself consists of 27.7 KSLOC 
of C code used to create the TCL interface.  The test scripts are contained
in 1343 files totaling 
23.5MB in size.  There are
50240 distinct test cases, but many of the test
cases are parameterized and run multiple times (with different parameters)
so that on a full test run millions of
separate tests are performed.




The TH3 test harness is a set of proprietary tests, written in
C that provide 100% branch test coverage 
(and 100% MC/DC test coverage) to
the core SQLite library.  The TH3 tests are designed to run
on embedded and specialized platforms that would not easily support
TCL or other workstation services.  TH3 tests use only the published 
SQLite interfaces. TH3 consists of about
75.7 MB or 1038.0 KSLOC
of C code implementing 49116 distinct test cases.
TH3 tests are heavily parameterized, though, so a full-coverage test runs
about 2.3 million different test
instances.  The cases that provide 100% branch test coverage constitute
a subset of the total TH3 test suite.  A soak test
prior to release does hundreds of millions of tests.
Additional information on TH3 is available separately.




The SQL Logic Test
or SLT test harness is used to run huge numbers
of SQL statements against both SQLite and several other SQL database engines
and verify that they all get the same answers.  SLT currently compares
SQLite against PostgreSQL, MySQL, Microsoft SQL Server, and Oracle 10g.
SLT runs 7.2 million queries comprising
1.12GB of test data.



The dbsqlfuzz engine is a
proprietary fuzz tester.  Other fuzzers for SQLite 
mutate either the SQL inputs or the database file.  Dbsqlfuzz mutates
both the SQL and the database file at the same time, and is thus able
to reach new error states.  Dbsqlfuzz is built using the
libFuzzer framework of LLVM
with a custom mutator.  There are
303 seed files. The dbsqlfuzz fuzzer
runs about one billion test mutations per day.
Dbsqlfuzz helps ensure
that SQLite is robust against attack via malicious SQL or database
inputs.


In addition to the four main test harnesses, there several other
small programs that implement specialized tests.

The "speedtest1.c" program 
estimates the performance of SQLite under a typical workload.  
The "mptester.c" program is a stress test for multiple processes 
concurrently reading and writing a single database.
The "threadtest3.c" program is a stress test for multiple threads using
SQLite simultaneously.  
The "fuzzershell.c" program is used to
run some fuzz tests.



All of the tests above must run successfully, on multiple platforms
and under multiple compile-time configurations,
before each release of SQLite.

Prior to each check-in to the SQLite source tree, developers
typically run a subset (called "veryquick") of the Tcl tests
consisting of about 
300.2 thousand test cases.
The veryquick tests include most tests other than the anomaly, fuzz, and 
soak tests.  The idea behind the veryquick tests are that they are
sufficient to catch most errors, but also run in only a few minutes
instead of a few hours.



3. Anomaly Testing

Anomaly tests are tests designed to verify the correct behavior
of SQLite when something goes wrong.  It is (relatively) easy to build
an SQL database engine that behaves correctly on well-formed inputs
on a fully functional computer.  It is more difficult to build a system
that responds sanely to invalid inputs and continues to function following
system malfunctions.  The anomaly tests are designed to verify the latter
behavior.



3.1. Out-Of-Memory Testing

SQLite, like all SQL database engines, makes extensive use of
malloc()  (See the separate report on
dynamic memory allocation in SQLite for
additional detail.)
On servers and workstations, malloc() never fails in practice and so correct
handling of out-of-memory (OOM) errors is not particularly important.
But on embedded devices, OOM errors are frighteningly common and since
SQLite is frequently used on embedded devices, it is important that
SQLite be able to gracefully handle OOM errors.

OOM testing is accomplished by simulating OOM errors.
SQLite allows an application to substitute an alternative malloc()
implementation using the sqlite3_config(SQLITE_CONFIG_MALLOC,...)
interface.  The TCL and TH3 test harnesses are both capable of
inserting a modified version of malloc() that can be rigged to fail 
after a certain number of allocations.  These instrumented mallocs
can be set to fail only once and then start working again, or to
continue failing after the first failure.  OOM tests are done in a
loop.  On the first iteration of the loop, the instrumented malloc
is rigged to fail on the first allocation.  Then some SQLite operation
is carried out and checks are done to make sure SQLite handled the
OOM error correctly.  Then the time-to-failure counter
on the instrumented malloc is increased by one and the test is
repeated.  The loop continues until the entire operation runs to
completion without ever encountering a simulated OOM failure.
Tests like this are run twice, once with the instrumented malloc
set to fail only once, and again with the instrumented malloc set
to fail continuously after the first failure.



3.2. I/O Error Testing

I/O error testing seeks to verify that SQLite responds sanely
to failed I/O operations.  I/O errors might result from a full disk drive,
malfunctioning disk hardware, network outages when using a network
file system, system configuration or permission changes that occur in the 
middle of an SQL operation, or other hardware or operating system 
malfunctions.  Whatever the cause, it is important that SQLite be able
to respond correctly to these errors and I/O error testing seeks to
verify that it does.

I/O error testing is similar in concept to OOM testing; I/O errors
are simulated and checks are made to verify that SQLite responds
correctly to the simulated errors.  I/O errors are simulated in both
the TCL and TH3 test harnesses by inserting a new
Virtual File System object that is specially rigged
to simulate an I/O error after a set number of I/O operations.
As with OOM error testing, the I/O error simulators can be set to
fail just once, or to fail continuously after the first failure.
Tests are run in a loop, slowly increasing the point of failure until
the test case runs to completion without error.  The loop is run twice,
once with the I/O error simulator set to simulate only a single failure
and a second time with it set to fail all I/O operations after the first
failure.

In I/O error tests, after the I/O error simulation failure mechanism
is disabled, the database is examined using
PRAGMA integrity_check to make sure that the I/O error has not
introduced database corruption.



3.3. Crash Testing

Crash testing seeks to demonstrate that an SQLite database will not
go corrupt if the application or operating system crashes or if there
is a power failure in the middle of a database update.  A separate
white-paper titled
Atomic Commit in SQLite describes the
defensive measure SQLite takes to prevent database corruption following
a crash.  Crash tests strive to verify that those defensive measures
are working correctly.

It is impractical to do crash testing using real power failures, of
course, and so crash testing is done in simulation.  An alternative
Virtual File System is inserted that allows the test
harness to simulate the state of the database file following a crash.

In the TCL test harness, the crash simulation is done in a separate
process.  The main testing process spawns a child process which runs
some SQLite operation and randomly crashes somewhere in the middle of
a write operation.  A special VFS randomly reorders and corrupts
the unsynchronized
write operations to simulate the effect of buffered filesystems.  After
the child dies, the original test process opens and reads the test
database and verifies that the changes attempted by the child either
completed successfully or else were completely rolled back.  The
integrity_check PRAGMA is used to make sure no database corruption
occurs.

The TH3 test harness needs to run on embedded systems that do not
necessarily have the ability to spawn child processes, so it uses
an in-memory VFS to simulate crashes.  The in-memory VFS can be rigged
to make a snapshot of the entire filesystem after a set number of I/O
operations.  Crash tests run in a loop.  On each iteration of the loop,
the point at which a snapshot is made is advanced until the SQLite
operations being tested run to completion without ever hitting a
snapshot.  Within the loop, after the SQLite operation under test has
completed, the filesystem is reverted to the snapshot and random file
damage is introduced that is characteristic of the kinds of damage
one expects to see following a power loss.  Then the database is opened
and checks are made to ensure that it is well-formed and that the
transaction either ran to completion or was completely rolled back.
The interior of the loop is repeated multiple times for each
snapshot with different random damage each time.



3.4. Compound failure tests

The test suites for SQLite also explore the result of stacking
multiple failures.  For example, tests are run to ensure correct behavior
when an I/O error or OOM fault occurs while trying to recover from a
prior crash.



4. Fuzz Testing

Fuzz testing
seeks to establish that SQLite responds correctly to invalid, out-of-range,
or malformed inputs.

4.1. SQL Fuzz

SQL fuzz testing consists of creating syntactically correct yet
wildly nonsensical SQL statements and feeding them to SQLite to see
what it will do with them.  Usually some kind of error is returned
(such as "no such table").  Sometimes, purely by chance, the SQL
statement also happens to be semantically correct.  In that case, the
resulting prepared statement is run to make sure it gives a reasonable
result.



4.1.1. SQL Fuzz Using The American Fuzzy Lop Fuzzer

The concept of fuzz testing has been around for decades, but fuzz
testing was not an effective way to find bugs until 2014 when
Michal Zalewski invented the first practical profile-guided fuzzer,
American Fuzzy Lop or "AFL".
Unlike prior fuzzers that blindly generate random inputs, AFL
instruments the program being tested (by modifying the assembly-language
output from the C compiler) and uses that instrumentation to detect when
an input causes the program to do something different - to follow
a new control path or loop a different number of times.  Inputs that provoke
new behavior are retained and further mutated.  In this way, AFL is able
to "discover" new behaviors of the program under test, including behaviors
that were never envisioned by the designers.

AFL proved adept at finding arcane bugs in SQLite.
Most of the findings have been assert() statements where the conditional
was false under obscure circumstances.  But AFL has also found
a fair number of crash bugs in SQLite, and even a few cases where SQLite 
computed incorrect results.

Because of its past success, AFL became a standard part of the testing
strategy for SQLite beginning with version 3.8.10 (2015-05-07) until
it was superseded by better fuzzers in version 3.29.0 (2019-07-10).



4.1.2. Google OSS Fuzz

Beginning in 2016, a team of engineers at Google started the
OSS Fuzz project.  
OSS Fuzz uses a AFL-style guided fuzzer running on Google's infrastructure.
The Fuzzer automatically downloads the latest check-ins for participating
projects, fuzzes them, and sends email to the developers reporting any
problems.  When a fix is checked in, the fuzzer automatically detects this
and emails a confirmation to the developers.

SQLite is one of many open-source projects that OSS Fuzz tests. The
test/ossfuzz.c source file
in the SQLite repository is SQLite's interface to OSS fuzz.

OSS Fuzz no longer finds historical bugs in SQLite.  But it is still
running and does occasionally find issues in new development check-ins.
Examples:
&#91;1&#93;
&#91;2&#93;
&#91;3&#93;.



4.1.3. The dbsqlfuzz fuzzer

Beginning in late 2018, SQLite has been fuzzed using a proprietary
fuzzer called "dbsqlfuzz".  Dbsqlfuzz is built using the 
libFuzzer framework of LLVM.

The dbsqlfuzz fuzzer mutates both the SQL input and the database file
at the same time.  Dbsqlfuzz uses a custom
Structure-Aware Mutator
on a specialized input file that defines both an input database and SQL
text to be run against that database. Because it mutates both the input
database and the input SQL at the same time, dbsqlfuzz has been able to
find some obscure faults in SQLite that were missed by prior fuzzers that
mutated only SQL inputs or only the database file.
The SQLite developers keep dbsqlfuzz running against trunk in about
16 cores at all times.  Each instance of dbsqlfuzz program is able to 
evalutes about 400 test cases per second, meaning that about 500 million
cases are checked every day.

The dbsqlfuzz fuzzer has been very successful at hardening the
SQLite code base against malicious attack.  Since dbsqlfuzz has been
added to the SQLite internal test suite, bug reports from external
fuzzers such as OSSFuzz have all but stopped.

Note that dbsqlfuzz is not the Protobuf-based structure-aware
fuzzer for SQLite that is used by Chromium and described in the
Structure-Aware Mutator article.
There is no connection between these two fuzzers, other than the fact that they
are both based on libFuzzer
The Protobuf fuzzer for SQLite is written and maintained by the Chromium
team at Google, whereas dbsqlfuzz is written and maintained by the original
SQLite developers.  Having multiple independently-developed fuzzers for SQLite
is good, as it means that obscure issues are more likely to be uncovered.



4.1.4. Other third-party fuzzers

SQLite seems to be a popular target for third-parties to fuzz.
The developers hear about many attempts to fuzz SQLite
and they do occasionally get bug reports found by independent
fuzzers.  All such reports are promptly fixed, so the product is
improved and that the entire SQLite user community benefits.
This mechanism of having many independent testers is similar to
Linus's law:
"given enough eyeballs, all bugs are shallow".

One fuzzing researcher of particular note is 
Manuel Rigger, currently
(as this paragraph is written on 2019-12-21)
at ETH Zurich.
Most fuzzers only look for assertion faults, crashes, undefined behavior (UB),
or other easily detected anomalies.  Dr. Rigger's fuzzers, on the other hand,
are able to find cases where SQLite computes an incorrect answer.
Rigger has found
many such cases.
Most of these finds are obscure corner cases involving type
conversions and affinity transformations, and a good number of the finds
are against unreleased features.  Nevertheless, his finds are still important
as they are real bugs,
and the SQLite developers are grateful to be able to identify and fix
the underlying problems.  Rigger's work is currently unpublished.  When it
is released, it could be as influential as Zalewski's invention of AFL
and profile-guided fuzzing.



4.1.5. The fuzzcheck test harness

Historical test cases from AFL, OSS Fuzz, and dbsqlfuzz are
collected in a set of database files in the main SQLite source tree
and then rerun by the "fuzzcheck" utility program whenever one runs
"make test".  Fuzzcheck only runs a few thousand "interesting" cases
out of the billions of cases that the various fuzzers have
examined over the years.  "Interesting" cases are cases that exhibit
previously unseen behavior.  Actual bugs found by fuzzers are always
included among the interesting test cases, but most of the cases run
by fuzzcheck were never actual bugs. 



4.1.6. Tension Between Fuzz Testing And 100% MC/DC Testing

Fuzz testing and 100% MC/DC testing are in tension with
one another.
That is to say, code tested to 100% MC/DC will tend to be
more vulnerable to problems found by fuzzing and code that performs
well during fuzz testing will tend to have (much) less than 
100% MC/DC.
This is because MC/DC testing discourages defensive code with
unreachable branches, but without defensive code, a fuzzer is
more likely to find a path that causes problems.  MC/DC testing
seems to work well for building code that is robust during
normal use, whereas fuzz testing is good for building code that is
robust against malicious attack.

Of course, users would prefer code that is both robust in normal
use and resistant to malicious attack.  The SQLite developers are
dedicated to providing that.  The purpose of this section is merely
to point out that doing both at the same time is difficult.

For much of its history SQLite has been focused on 100% MC/DC testing.
Resistance to fuzzing attacks only became a concern with the introduction
of AFL in 2014.  For a while there, fuzzers were finding many problems
in SQLite.  In more recent years, the testing strategy of SQLite has
evolved to place more emphasis on fuzz testing.  We still maintain
100% MC/DC of the core SQLite code, but most testing CPU cycles are 
now devoted to fuzzing.

While fuzz testing and 100% MC/DC testing are in tension, they
are not completely at cross-purposes.  The fact that the SQlite test
suite does test to 100% MC/DC means that when fuzzers do find problems,
those problems can be fixed quickly and with little risk of introducing
new errors.

4.2. Malformed Database Files

There are numerous test cases that verify that SQLite is able to
deal with malformed database files.
These tests first build a well-formed database file, then add
corruption by changing one or more bytes in the file by some means
other than SQLite.  Then SQLite is used to read the database.
In some cases, the bytes changes are in the middle of data.
This causes the content of the database to change while keeping the
database well-formed.
In other cases, unused bytes of the file are modified, which has
no effect on the integrity of the database.
The interesting cases are when bytes of the file that
define database structure get changed.  The malformed database tests
verify that SQLite finds the file format errors and reports them
using the SQLITE_CORRUPT return code without overflowing
buffers, dereferencing NULL pointers, or performing other
unwholesome actions.

The dbsqlfuzz fuzzer also does an excellent job of verifying
that SQLite responds sanely to malformed database files.

4.3. Boundary Value Tests

SQLite defines certain limits on its operation, such as the
maximum number of columns in a table, the maximum length of an 
SQL statement, or the maximum value of an integer.  The TCL and TH3 test
suites both contains numerous tests that push SQLite right to the edge
of its defined limits and verify that it performs correctly for
all allowed values.  Additional tests go beyond the defined limits
and verify that SQLite correctly returns errors.  The source code
contains testcase macros to verify that both sides of each boundary
have been tested.



5. Regression Testing

Whenever a bug is reported against SQLite, that bug is not considered
fixed until new test cases that would exhibit the bug have been added 
to either the TCL or TH3 test suites.
Over the years,
this has resulted in thousands and thousands of new tests.
These regression tests ensure that bugs that have
been fixed in the past are not reintroduced into future versions of
SQLite.



6. Automatic Resource Leak Detection

Resource leak occurs when system resources
are allocated and never freed.  The most troublesome resource leaks
in many applications are memory leaks - when memory is allocated using
malloc() but never released using free().  But other kinds of resources
can also be leaked:  file descriptors, threads, mutexes, etc.

Both the TCL and TH3 test harnesses automatically track system
resources and report resource leaks on every test run.
No special configuration or setup is required.   The test harnesses
are especially vigilant with regard to memory leaks.  If a change
causes a memory leak, the test harnesses will recognize this
quickly.  SQLite is designed to never leak memory, even after
an exception such as an OOM error or disk I/O error.  The test
harnesses are zealous to enforce this.



7. Test Coverage

The SQLite core, including the unix VFS,
has 100% branch test coverage under TH3 in
its default configuration as measured by
gcov.
Extensions such as FTS3 and RTree are excluded from this
analysis.



7.1. Statement versus branch coverage

There are many ways to measure test coverage.  The most popular
metric is "statement coverage".  When you hear someone say that their
program as "XX% test coverage" without further explanation, they usually
mean statement coverage.  Statement coverage measures what percentage
of lines of code are executed at least once by the test suite.

Branch coverage is more rigorous than statement coverage.  Branch
coverage measures the number of machine-code branch instructions that
are evaluated at least once on both directions.

To illustrate the difference between statement coverage and
branch coverage, consider the following hypothetical
line of C code:

if( a>b && c!=25 ){ d++; }


Such a line of C code might generate a dozen separate machine code
instructions.  If any one of those instructions is ever evaluated, then
we say that the statement has been tested.  So, for example, it might
be the case that the conditional expression is
always false and the "d" variable is
never incremented.  Even so, statement coverage counts this line of
code as having been tested.

Branch coverage is more strict.  With branch coverage, each test and
each subblock within the statement is considered separately.  In order
to achieve 100% branch coverage in the example above, there must be at
least three test cases:


 a&lt;=b
 a&gt;b && c==25
 a&gt;b && c!=25


Any one of the above test cases would provide 100% statement coverage
but all three are required for 100% branch coverage.  Generally speaking,
100% branch coverage implies 100% statement coverage, but the converse is
not true.  To reemphasize, the
TH3 test harness for SQLite provides the stronger form of
test coverage - 100% branch test coverage.



7.2. Coverage testing of defensive code

A well-written C program will typically contain some defensive
conditionals which in practice are always true or always false.
This leads to a 
programming dilemma:  Does one remove defensive code in order to obtain
100% branch coverage?

In SQLite, the answer to the previous question is "no".
For testing purposes, the SQLite source code defines
macros called ALWAYS() and NEVER().   The ALWAYS() macro
surrounds conditions
which are expected to always evaluate as true and NEVER() surrounds
conditions that are always evaluated to false.  These macros serve as
comments to indicate that the conditions are defensive code.
In release builds, these macros are pass-throughs:

#define ALWAYS(X)  (X)
#define NEVER(X)   (X)


During most testing, however, these macros will throw an assertion
fault if their argument does not have the expected truth value.  This
alerts the developers quickly to incorrect design assumptions.

#define ALWAYS(X)  ((X)?1:assert(0),0)
#define NEVER(X)   ((X)?assert(0),1:0)


When measuring test coverage, these macros are defined to be constant
truth values so that they do not generate assembly language branch
instructions, and hence do not come into play when calculating the
branch coverage:

#define ALWAYS(X)  (1)
#define NEVER(X)   (0)


The test suite is designed to be run three times, once for each of
the ALWAYS() and NEVER() definitions shown above.  All three test runs
should yield exactly the same result.  There is a run-time test using
the sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, ...) interface that
can be used to verify that the macros are correctly set to the first
form (the pass-through form) for deployment.



7.3. Forcing coverage of boundary values and boolean vector tests

Another macro used in conjunction with test coverage measurement is
the testcase() macro.  The argument is a condition for which
we want test cases that evaluate to both true and false.
In non-coverage builds (that is to say, in release builds) the
testcase() macro is a no-op:

#define testcase(X)


But in a coverage measuring build, the testcase() macro
generates code that evaluates the conditional expression in its argument.  
Then during analysis, a check
is made to ensure tests exist that evaluate the conditional to both true
and false.  Testcase() macros are used, for example, to help verify
that boundary values are tested.  For example:

testcase( a==b );
testcase( a==b+1 );
if( a>b && c!=25 ){ d++; }


Testcase macros are also used when two or more cases of a switch
statement go to the same block of code, to make sure that the code was
reached for all cases:

switch( op ){
  case OP_Add:
  case OP_Subtract: {
    testcase( op==OP_Add );
    testcase( op==OP_Subtract );
    /* ... */
    break;
  }
  /* ... */
}


For bitmask tests, testcase() macros are used to verify that every
bit of the bitmask affects the outcome.  For example, in the following block
of code, the condition is true if the mask contains either of two bits
indicating either a MAIN_DB or a TEMP_DB is being opened.  
The testcase()
macros that precede the if statement verify that both cases are tested:

testcase( mask & SQLITE_OPEN_MAIN_DB );
testcase( mask & SQLITE_OPEN_TEMP_DB );
if( (mask & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB))!=0 ){ ... }


The SQLite source code contains 1143
uses of the testcase() macro.



7.4. Branch coverage versus MC/DC

Two methods of measuring test coverage were described above:
"statement" and "branch" coverage.  There are many other test coverage
metrics besides these two.  Another popular metric is "Modified
Condition/Decision Coverage" or MC/DC.  
Wikipedia
defines MC/DC as follows:


 Each decision tries every possible outcome.
 Each condition in a decision takes on every possible outcome.
 Each entry and exit point is invoked.
 Each condition in a decision is shown to independently
     affect the outcome of the decision.


In the C programming language 
where &amp;&amp; and ||
are "short-circuit" operators, MC/DC and branch coverage are very nearly
the same thing.  The primary difference is in boolean vector tests.
One can test for any of several bits in bit-vector and still obtain
100% branch test coverage even though the second element of MC/DC - the
requirement that each condition in a decision take on every possible outcome -
might not be satisfied.

SQLite uses testcase() macros as described in the previous
subsection to make sure that every condition in a bit-vector decision takes
on every possible outcome.  In this way, SQLite also achieves 100% MC/DC
in addition to 100% branch coverage.

7.5. Measuring branch coverage

Branch coverage in SQLite is currently measured
using gcov with the "-b"
option.  First the test program is compiled using options
"-g -fprofile-arcs -ftest-coverage" and then the test program is run.
Then "gcov -b" is run to generate a coverage report.
The coverage report is verbose and inconvenient to read, 
so the gcov-generated report is processed using
some simple scripts to put it into a more human-friendly format.
This entire process is automated using scripts, of course.

Note that running SQLite with gcov is not a test of SQLite &mdash;
it is a test of the test suite.  The gcov run does not test SQLite because
the -fprofile-args and -ftest-coverage options cause the compiler to 
generate different code.  
The gcov run merely verifies that the test suite provides 100% branch test
coverage.  The gcov run is a test of the test - a meta-test.

After gcov has been run to verify 100% branch test coverage,
then the test program is recompiled using delivery compiler options
(without the special -fprofile-arcs and -ftest-coverage options)
and the test program is rerun.
This second run is the actual test of SQLite.

It is important to verify that the gcov test run 
and the second real test run both give the same output.  Any
differences in output indicate either the use of undefined or
indeterminate behavior in the SQLite code (and hence a bug), 
or a bug in the compiler.
Note that SQLite has, over the previous decade, encountered bugs
in each of GCC, Clang, and MSVC.  Compiler bugs, while rare, do happen,
which is why it is so important to test the code in an as-delivered
configuration.



7.6. Mutation testing

Using gcov (or similar) to show that every branch instruction is taken
at least once in both directions is good measure of test suite quality.
But even better is showing that every branch instruction makes
a difference in the output.  In other words, we want to show 
not only that every branch instruction both jumps and falls through but also
that every branch is doing useful work and that the test suite is able
to detect and verify that work.  When a branch is found that does not
make a difference in the output, that suggests that the code associated 
the branch can be removed (reducing the size of the library and perhaps
making it run faster) or that the test suite is inadequately testing the
feature that the branch implements.

SQLite strives to verify that every branch instruction makes a difference
using mutation testing.
A script
first compiles the SQLite source code into assembly language
(using, for example, the -S option to gcc).  Then the script steps through
the generated assembly language and, one by one, changes each branch 
instruction into either an unconditional jump or a no-op, compiles the 
result, and verifies that the test suite catches the mutation.


Unfortunately, SQLite contains many branch instructions that
help the code run faster without changing the output.
Such branches generate false-positives during mutation testing.
As an example, consider the following 
hash function
used to accelerate table-name lookup:

55  static unsigned int strHash(const char *z){
56    unsigned int h = 0;
57    unsigned char c;
58    while( (c = (unsigned char)*z++)!=0 ){     /*OPTIMIZATION-IF-TRUE*/
59      h = (h&lt;&lt;3) &#94; h &#94; sqlite3UpperToLower&#91;c&#93;;
60    }
61    return h;
62  }



If the branch instruction that implements the "c!=0" test on line 58
is changed into a no-op, then the while-loop will loop forever and the
test suite will fail with a time-out.  But if that branch is changed
into an unconditional jump, then the hash function will always return 0.
The problem is that 0 is a valid hash.  A hash function that always
returns 0 still works in the sense that SQLite still always gets the correct
answer.  The table-name hash table degenerates into a linked-list
and so the table-name lookups that occur while parsing SQL statements 
might be a little slower, but the end result will be the same.


To work around this problem, comments of the form
"/*OPTIMIZATION-IF-TRUE*/" and
"/*OPTIMIZATION-IF-FALSE*/" are inserted into the SQLite
source code to tell the mutation testing script to ignore some branch
instructions.



7.7. Experience with full test coverage

The developers of SQLite have found that full coverage testing is an
extremely effective method for locating and preventing bugs.
Because every single branch
instruction in SQLite core code is covered by test cases, the developers
can be confident that changes made in one part of the code
do not have unintended consequences in other parts of the code.
The many new features and performance improvements that have been
added to SQLite in recent years would not have been possible without
the availability of full-coverage testing.

Maintaining 100% MC/DC is laborious and time-consuming.
The level of effort needed to maintain full-coverage testing
is probably not cost effective for a typical application.
However, we think that full-coverage testing is justified for a
very widely deployed infrastructure library
like SQLite, and especially for a database library which by its very
nature "remembers" past mistakes.




8. Dynamic Analysis

Dynamic analysis refers to internal and external checks on the
SQLite code which are performed while the code is live and running.
Dynamic analysis has proven to be a great help in maintaining the
quality of SQLite.



8.1. Assert

The SQLite core contains 6548 assert()
statements that verify function preconditions and postconditions and
loop invariants.  Assert() is a macro which is a standard part of
ANSI-C.  The argument is a boolean value that is assumed to always be
true.  If the assertion is false, the program prints an error message
and halts.

Assert() macros are disabled by compiling with the NDEBUG macro defined.
In most systems, asserts are enabled by default.  But in SQLite, the
asserts are so numerous and are in such performance critical places, that
the database engine runs about three times slower when asserts are enabled.
Hence, the default (production) build of SQLite disables asserts.  
Assert statements are only enabled when SQLite is compiled with the
SQLITE_DEBUG preprocessor macro defined.

See the Use Of assert in SQLite document
for additional information about how SQLite uses assert().



8.2. Valgrind

Valgrind is perhaps the most amazing
and useful developer tool in the world.  Valgrind is a simulator - it simulates
an x86 running a Linux binary.  (Ports of Valgrind for platforms other
than Linux are in development, but as of this writing, Valgrind only
works reliably on Linux, which in the opinion of the SQLite developers 
means that Linux should be the preferred platform for all software development.)
As Valgrind runs a Linux binary, it looks for all kinds of interesting
errors such as array overruns, reading from uninitialized memory,
stack overflows, memory leaks, and so forth.  Valgrind finds problems
that can easily slip through all of the other tests run against SQLite.
And, when Valgrind does find an error, it can dump the developer directly
into a symbolic debugger at the exact point where the error occur, to
facilitate a quick fix.

Because it is a simulator, running a binary in Valgrind is slower than 
running it on native hardware.  (To a first approximation, an application
running in Valgrind on a workstation will perform about the same as it
would running natively on a smartphone.)  So it is impractical to run the full
SQLite test suite through Valgrind.  However, the veryquick tests and
the coverage of the TH3 tests are run through Valgrind prior to every
release.



8.3. Memsys2

SQLite contains a pluggable
memory allocation subsystem.
The default implementation uses system malloc() and free(). 
However, if SQLite is compiled with SQLITE_MEMDEBUG, an alternative
memory allocation wrapper (memsys2)
is inserted that looks for memory allocation
errors at run-time.  The memsys2 wrapper checks for memory leaks, of
course, but also looks for buffer overruns, uses of uninitialized memory,
and attempts to use memory after it has been freed.  These same checks
are also done by valgrind (and, indeed, Valgrind does them better)
but memsys2 has the advantage of being much faster than Valgrind, which
means the checks can be done more often and for longer tests.



8.4. Mutex Asserts

SQLite contains a pluggable mutex subsystem.  Depending on 
compile-time options, the default mutex system contains interfaces
sqlite3_mutex_held() and sqlite3_mutex_notheld() that detect
whether or not a particular mutex is held by the calling thread.
These two interfaces are used extensively within assert() statements
in SQLite to verify mutexes are held and released at all the right
moments, in order to double-check that SQLite does work correctly
in multi-threaded applications.



8.5. Journal Tests

One of the things that SQLite does to ensure that transactions
are atomic across system crashes and power failures is to write
all changes into the rollback journal file prior to changing the
database.  The TCL test harness contains an alternative
OS backend implementation that helps to
verify this is occurring correctly.  The "journal-test VFS" monitors
all disk I/O traffic between the database file and rollback journal,
checking to make sure that nothing is written into the database
file which has not first been written and synced to the rollback journal.
If any discrepancies are found, an assertion fault is raised.

The journal tests are an additional double-check over and above
the crash tests to make sure that SQLite transactions will be atomic
across system crashes and power failures.



8.6. Undefined Behavior Checks

In the C programming language, it is very easy to write code that
has "undefined" or "implementation defined" behavior.
That means that the code might work during development, but then give
a different answer on a different system, or when recompiled using different
compiler options.  
Examples of undefined and implementation-defined behavior in
ANSI C include:

Signed integer overflow.  (Signed integer overflow does not
necessarily wrap around, as most people expect.)
Shifting an N-bit integer by more than N bits.
Shifting by a negative amount.
Shifting a negative number.
Using the memcpy() function on overlapping buffers.
The order of evaluation of function arguments.
Whether or not "char" variables are signed or unsigned.
And so forth....


Since undefined and implementation-defined behavior is non-portable
and can easily lead to incorrect answers, SQLite works very hard to avoid it.
For example,
when adding two integer column values together as part of an SQL statement,
SQLite does not simply add them together using the C-language "+" operator.
Instead, it first checks to make sure the
addition will not overflow, and if it will, it does the addition using
floating point instead.

To help ensure that SQLite does not make use of undefined or
implementation defined behavior, the test suites are rerun using
instrumented builds that try to detect undefined behavior.  For example,
test suites are run using the "-ftrapv" option of GCC.  And they
are run again using the "-fsanitize=undefined" option on Clang.  And
again using the "/RTC1" option in MSVC.  Then the test suites are rerun
using options like "-funsigned-char" and "-fsigned-char" to make sure
that implementation differences do not matter either.  Tests are then repeated
on 32-bit and 64-bit systems and on big-endian and little-endian systems,
using a variety of CPU architectures.
Furthermore, the test suites are augmented with many test cases that are
deliberately designed to provoke undefined behavior.  For example:
"SELECT -1*(-9223372036854775808);".



9. Disabled Optimization Tests

The sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, ...) interface
allows selected SQL statement optimizations to be disabled at run-time.
SQLite should always generate exactly the same answer with optimizations
enabled and with optimizations disabled; the answer simply arrives quicker
with the optimizations turned on.  So in a production environment, one always
leaves the optimizations turned on (the default setting).

One verification technique used on SQLite is to run an entire test suite
twice, once with optimizations left on and a second time with optimizations
turned off, and verify that the same output is obtained both times.  This
shows that the optimizations do not introduce errors.

Not all test cases can be handled this way.  Some test cases check
to verify that the optimizations really are reducing the amount of
computation by counting the number of disk accesses, sort operations, 
full-scan steps, or other processing steps that occur during queries.
Those test cases will appear to fail when optimizations are disabled.
But the majority of test cases simply check that the correct answer
was obtained, and all of those cases can be run successfully with and
without the optimizations, in order to show that the optimizations do not
cause malfunctions.




10. Checklists

The SQLite developers use an on-line checklist to coordinate testing
activity and to verify that all tests pass prior each SQLite release.
Past checklists
are retained for historical reference.
(The checklists are read-only for anonymous internet viewers, but
developers can log in and update checklist items in their web
browsers.)
The use of checklists for SQLite testing and other development activities
is inspired by 
The Checklist Manifesto
.

The latest checklists contain approximately 200 items that are
individually verified for each release.  Some checklist items only take
a few seconds to verify and mark off.  Others involve test suites
that run for many hours.

The release checklist is not automated: developers run each item on
the checklist manually.  We find that it is important to keep a human in
the loop.  Sometimes problems are found while running a checklist item
even though the test itself passed.  It is important to have a human
reviewing the test output at the highest level, and constantly asking
"Is this really right?"

The release checklist is continuously evolving.  As new problems or
potential problems are discovered, new checklist items are added to
make sure those problems do not appear in subsequent releases.  The
release checklist has proven to be an invaluable tool in helping to
ensure that nothing is overlooked during the release process.




11. Static Analysis

Static analysis means analyzing source code at compile-time to
check for correctness.  Static analysis includes compiler
warning messages and more in-depth analysis engines such as the
Clang Static Analyzer.
SQLite compiles without warnings on GCC and Clang using 
the -Wall and -Wextra flags on Linux and Mac and on MSVC on Windows.
No valid warnings are generated by the Clang Static Analyzer tool "scan-build"
either (though recent versions of clang seem to generate many false-positives.)
Nevertheless, some warnings might be generated by other
static analyzers.  Users are encouraged not to stress over these
warnings and to instead take solace in the intense testing of SQLite
described above. 


Static analysis has not been helpful in finding
bugs in SQLite.  Static analysis has found a few bugs in SQLite, but
those are the exceptions.  More bugs have been
introduced into SQLite while trying to get it to compile without 
warnings than have been found by static analysis.



12. Summary

SQLite is open source.  This gives many people the idea that
it is not well tested as commercial software and is perhaps unreliable.
But that impression is false.  
SQLite has exhibited very high reliability in the field and
a very low defect rate, especially considering how rapidly it is evolving.
The quality of SQLite is achieved in part by careful code design and
implementation.  But extensive testing also plays a vital role in
maintaining and improving the quality of SQLite.  This document has
summarized the testing procedures that every release of SQLite undergoes
with the hope of inspiring confidence that SQLite is
suitable for use in mission-critical applications.
This page last modified on  2022-05-31 20:17:58 UTC


