sqlite/www/34to35.tcl
drh 7a64b6a31c Use sqlite3_int64, not sqlite_in64, consistently in the documentation.
Ticket #2680. (CVS 4448)

FossilOrigin-Name: f7a2647033817c73f40010e145e4c29173a55689
2007-10-01 13:54:11 +00:00

1007 lines
42 KiB
Tcl

#
# Run this TCL script to generate HTML for the goals.html file.
#
set rcsid {$Id: 34to35.tcl,v 1.4 2007/10/01 13:54:11 drh Exp $}
source common.tcl
header {SQLite Changes From Version 3.4.2 To 3.5.0}
proc CODE {text} {
puts "<blockquote><pre>"
puts $text
puts "</pre></blockquote>"
}
proc SYNTAX {text} {
puts "<blockquote><pre>"
set t2 [string map {& &amp; < &lt; > &gt;} $text]
regsub -all "/(\[^\n/\]+)/" $t2 {</b><i>\1</i><b>} t3
puts "<b>$t3</b>"
puts "</pre></blockquote>"
}
proc IMAGE {name {caption {}}} {
puts "<center><img src=\"$name\">"
if {$caption!=""} {
puts "<br>$caption"
}
puts "</center>"
}
proc PARAGRAPH {text} {
# regsub -all "/(\[a-zA-Z0-9\]+)/" $text {<i>\1</i>} t2
#regsub -all "\\*(\[^\n*\]+)\\*" $text {<tt><b><big>\1</big></b></tt>} t3
regsub -all {\[([^]\n]+)\]} $text {[resolve_link \1]} t3
puts "<p>[subst -novar -noback $t3]</p>\n"
}
proc resolve_link {args} {
set a2 [split $args |]
set id [string trim [lindex $a2 0]]
if {[lindex $a2 1]==""} {
set display [string trim [lindex $a2 0]]
} else {
set display [string trim [lrange $a2 1 end]]
}
regsub -all {[^a-zA-Z0-9_]} $id {} id
return "<a href=\"capi3ref.html#$id\">$display</a>"
}
set level(0) 0
set level(1) 0
proc HEADING {n name {tag {}}} {
if {$tag!=""} {
puts "<a name=\"$tag\">"
}
global level
incr level($n)
for {set i [expr {$n+1}]} {$i<10} {incr i} {
set level($i) 0
}
if {$n==0} {
set num {}
} elseif {$n==1} {
set num $level(1).0
} else {
set num $level(1)
for {set i 2} {$i<=$n} {incr i} {
append num .$level($i)
}
}
incr n 1
puts "<h$n>$num $name</h$n>"
}
HEADING 0 {Moving From SQLite 3.4.2 to 3.5.0}
PARAGRAPH {
SQLite version 3.5.0 introduces a new OS interface layer that
is incompatible with all prior versions of SQLite. In addition,
a few existing interfaces have been generalized to work across all
database connections within a process rather than just all
connections within a thread. The purpose of this article
is to describe the changes to 3.5.0 in detail so that users
of prior versions of SQLite can judge what, if any, effort will
be required to upgrade to newer versions.
}
HEADING 1 {Overview Of Changes}
PARAGRAPH {
A quick enumeration of the changes in SQLite version 3.5.0
is provide here. Subsequent sections will describe these
changes in more detail.
}
PARAGRAPH {
<ol>
<li>The OS interface layer has been completely reworked:
<ol type="a">
<li>The undocumented <b>sqlite3_os_switch()</b> interface has
been removed.</li>
<li>The <b>SQLITE_ENABLE_REDEF_IO</b> compile-time flag no longer functions.
I/O procedures are now always redefinable.</li>
<li>Three new objects are defined for specifying I/O procedures:
[sqlite3_vfs], [sqlite3_file], and [sqlite3_io_methods].</li>
<li>Three new interfaces are used to create alternative OS interfaces:
[sqlite3_vfs_register()], [sqlite3_vfs_unregister()], and
[sqlite3_vfs_find()].</li>
<li>A new interface has been added to provided additional control over
the creation of new database connections: [sqlite3_open_v2()].
The legacy interfaces of [sqlite3_open()] and
[sqlite3_open16()] continue to be fully supported.</li>
</ol></li>
<li>The optional shared cache and memory management features that
were introduced in version 3.3.0 can now be used across multiple
threads within the same process. Formerly, these extensions only
applied to database connections operating within a single thread.
<ol type="a">
<li>The [sqlite3_enable_shared_cache()] interface now applies to all
threads within a process, not to just the one thread in which it
was run.</li>
<li>The [sqlite3_soft_heap_limit()] interface now applies to all threads
within a process, not to just the one thread in which it was run.</li>
<li>The [sqlite3_release_memory()] interface will now attempt to reduce
the memory usages across all database connections in all threads, not
just connections in the thread where the interface is called.</li>
<li>The [sqlite3_thread_cleanup()] interface has become a no-op.</li>
</ol></li>
<li>Restrictions on the use of the same database connection by multiple
threads have been dropped. It is now safe for
multiple threads to use the same database connection at the same
time.</li>
<li>There is now a compile-time option that allows an application to
define alternative malloc()/free() implementations without having
to modify any core SQLite code.</li>
<li>There is now a compile-time option that allows an application to
define alternative mutex implementations without having
to modify any core SQLite code.</li>
</ol>
}
PARAGRAPH {
Of these changes, only 1a and 2a through 2c are incompatibilities
in any formal sense.
But users who have previously made custom modifications to the
SQLite source (for example to add a custom OS layer for embedded
hardware) might find that these changes have a larger impact.
On the other hand, an important goal of these changes is to make
it much easier to customize SQLite for use on different operating
systems.
}
HEADING 1 {The OS Interface Layer}
PARAGRAPH {
If your system defines a custom OS interface for SQLite or if you
were using the undocumented <b>sqlite3_os_switch()</b>
interface, then you will need to make modifications in order to
upgrade to SQLite version 3.5.0. This may seem painful at first
glance. But as you look more closely, you will probably discover
that your changes are made smaller and easier to understand and manage
by the new SQLite interface. It is likely that your changes will
now also work seamlessly with the SQLite amalgamation. You will
no longer need to make any changes to the code SQLite source code.
All of your changes can be effected by application code and you can
link against a standard, unmodified version of the SQLite amalgamation.
Furthermore, the OS interface layer, which was formerly undocumented,
is now an officially support interface for SQLite. So you have
some assurance that this will be a one-time change and that your
new backend will continue to work in future versions of SQLite.
}
HEADING 2 {The Virtual File System Object}
PARAGRAPH {
The new OS interface for SQLite is built around an object named
[sqlite3_vfs]. The "vfs" standard for "Virtual File System".
The sqlite3_vfs object is basically a structure containing pointers
to functions that implement the primitive disk I/O operations that
SQLite needs to perform in order to read and write databases.
In this article, we will often refer a sqlite3_vfs objects as a "VFS".
}
PARAGRAPH {
SQLite is able to use multiple VFSes at the same time. Each
individual database connection is associated with just one VFS.
But if you have multiple database connections, each connection
can be associated with a different VFS.
}
PARAGRAPH {
There is always a default VFS.
The legacy interfaces [sqlite3_open()] and [sqlite3_open16()] always
use the default VFS.
The new interface for creating database connections,
[sqlite3_open_v2()], allows you to specify which VFS you want to
use by name.
}
HEADING 3 {Registering New VFS Objects}
PARAGRAPH {
Standard builds of SQLite for unix or windows come with a single
VFS named "unix" or "win32", as appropriate. This one VFS is also
the default. So if you are using the legacy open functions, everything
will continue to operate as it has before. The change is that an application
now has the flexibility of adding new VFS modules to implement a
customized OS layer. The [sqlite3_vfs_register()] API can be used
to tell SQLite about one or more application-defined VFS modules:
}
CODE {
int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
}
PARAGRAPH {
Applications can call sqlite3_vfs_register at any time, though of course
a VFS needs to be registered before it can be used. The first argument
is a pointer to a customized VFS object that the application has prepared.
The second argument is true to make the new VFS the default VFS so that
it will be used by the legacy [sqlite3_open()] and [sqlite3_open16()] APIs.
If the new VFS is not the default, then you will probably have to use
the new [sqlite3_open_v2()] API to use it. Note, however, that if
a new VFS is the only VFS known to SQLite (if SQLite was compiled without
its usual default VFS or if the pre-compiled default VFS was removed
using [sqlite3_vfs_unregister()]) then the new VFS automatic becomes the
default VFS regardless of the makeDflt argument to [sqlite3_vfs_register()].
}
PARAGRAPH {
Standard builds include the default "unix" or "win32" VFSes.
But if you use the -DOS_OTHER=1 compile-time option, then SQLite is
built without a default VFS. In that case, the application must
register at least one VFS prior to calling [sqlite3_open()].
This is the approach that embedded applications should use.
Rather than modifying the SQLite source to to insert an alternative
OS layer as was done in prior releases of SQLite, instead compile
an unmodified SQLite source file (preferably the amalgamation)
with the -DOS_OTHER=1 option, then invoke [sqlite3_vfs_register()]
to define the interface to the underlying filesystem prior to
creating any database connections.
}
HEADING 3 {Additional Control Over VFS Objects}
PARAGRAPH {
The [sqlite3_vfs_unregister()] API is used to remove an existing
VFS from the system.
}
CODE {
int sqlite3_vfs_unregister(sqlite3_vfs*);
}
PARAGRAPH {
The [sqlite3_vfs_find()] API is used to locate a particular VFS
by name. Its prototype is as follows:
}
CODE {
sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
}
PARAGRAPH {
The argument is the symbolic name for the desired VFS. If the
argument is a NULL pointer, then the default VFS is returned.
The function returns a pointer to the [sqlite3_vfs] object that
implements the VFS. Or it returns a NULL pointer if no object
could be found that matched the search criteria.
}
HEADING 3 {Modifications Of Existing VFSes}
PARAGRAPH {
Once a VFS has been registered, it should never be modified. If
a change in behavior is required, a new VFS should be registered.
The application could, perhaps, use [sqlite3_vfs_find()] to locate
the old VFS, make a copy of the old VFS into a new [sqlite3_vfs]
object, make the desired modifications to the new VFS, unregister
the old VFS, the register the new VFS in its place. Existing
database connections would continue to use the old VFS even after
it is unregistered, but new database connections would use the
new VFS.
}
HEADING 3 {The VFS Object}
PARAGRAPH {
A VFS object is an instance of the following structure:
}
CODE {
typedef struct sqlite3_vfs sqlite3_vfs;
struct sqlite3_vfs {
int iVersion; /* Structure version number */
int szOsFile; /* Size of subclassed sqlite3_file */
int mxPathname; /* Maximum file pathname length */
sqlite3_vfs *pNext; /* Next registered VFS */
const char *zName; /* Name of this virtual file system */
void *pAppData; /* Pointer to application-specific data */
int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
int flags, int *pOutFlags);
int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
int (*xAccess)(sqlite3_vfs*, const char *zName, int flags);
int (*xGetTempName)(sqlite3_vfs*, char *zOut);
int (*xFullPathname)(sqlite3_vfs*, const char *zName, char *zOut);
void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol);
void (*xDlClose)(sqlite3_vfs*, void*);
int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
int (*xSleep)(sqlite3_vfs*, int microseconds);
int (*xCurrentTime)(sqlite3_vfs*, double*);
/* New fields may be appended in figure versions. The iVersion
** value will increment whenever this happens. */
};
}
PARAGRAPH {
To create a new VFS, an application fills in an instance of this
structure with appropriate values and then calls [sqlite3_vfs_register()].
}
PARAGRAPH {
The iVersion field of [sqlite3_vfs] should be 1 for SQLite version 3.5.0.
This number may increase in future versions of SQLite if we have to
modify the VFS object in some way. We hope that this never happens,
but the provision is made in case it does.
}
PARAGRAPH {
The szOsFile field is the size in bytes of the structure that defines
an open file: the [sqlite3_file] object. This object will be described
more fully below. The point here is that each VFS implementation can
define its own [sqlite3_file] object containing whatever information
the VFS implementation needs to store about an open file. SQLite needs
to know how big this object is, however, in order to preallocate enough
space to hold it.
}
PARAGRAPH {
The mxPathname field is the maximum length of a file pathname that
this VFS can use. SQLite sometimes has to preallocate buffers of
this size, so it should be as small as reasonably possible. Some
filesystems permit huge pathnames, but in practice pathnames rarely
extend beyond 100 bytes or so. You do not have to put the longest
pathname that the underlying filesystem can handle here. You only
have to put the longest pathname that you want SQLite to be able to
handle. A few hundred is a good value in most cases.
}
PARAGRAPH {
The pNext field is used internally by SQLite. Specifically, SQLite
uses this field to form a linked list of registered VFSes.
}
PARAGRAPH {
The zName field is the symbolic name of the VFS. This is the name
that the [sqlite3_vfs_find()] compares against when it is looking for
a VFS.
}
PARAGRAPH {
The pAppData pointer is unused by the SQLite core. The pointer is
available to store auxiliary information that a VFS information might
want to carry around.
}
PARAGRAPH {
The remaining fields of the [sqlite3_vfs] object all store pointer
to functions that implement primitive operations. We call these
"methods". The first methods, xOpen, is used to open files on
the underlying storage media. The result is an [sqlite3_file]
object. There are additional methods, defined by the [sqlite3_file]
object itself that are used to read and write and close the file.
The additional methods are detailed below. The filename is in UTF-8.
SQLite will guarantee that the zFilename string passed to
xOpen() is a full pathname as generated by xFullPathname() and
that the string will be valid and unchanged until xClose() is
called. So the [sqlite3_file] can store a pointer to the
filename if it needs to remember the filename for some reason.
The flags argument to xOpen() is a copy of the flags argument
to sqlite3_open_v2(). If sqlite3_open() or sqlite3_open16()
is used, then flags is [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
If xOpen() opens a file read-only then it sets *pOutFlags to
include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be
set.
SQLite will also add one of the following flags to the xOpen()
call, depending on the object being opened:
<ul>
<li> [SQLITE_OPEN_MAIN_DB]
<li> [SQLITE_OPEN_MAIN_JOURNAL]
<li> [SQLITE_OPEN_TEMP_DB]
<li> [SQLITE_OPEN_TEMP_JOURNAL]
<li> [SQLITE_OPEN_TRANSIENT_DB]
<li> [SQLITE_OPEN_SUBJOURNAL]
<li> [SQLITE_OPEN_MASTER_JOURNAL]
</ul>
The file I/O implementation can use the object type flags to
changes the way it deals with files. For example, an application
that does not care about crash recovery or rollback, might make
the open of a journal file a no-op. Writes to this journal are
also a no-op. Any attempt to read the journal returns [SQLITE_IOERR].
Or the implementation might recognize the a database file will
be doing page-aligned sector reads and writes in a random order
and set up its I/O subsystem accordingly.
SQLite might also add one of the following flags to the xOpen
method:
<ul>
<li> [SQLITE_OPEN_DELETEONCLOSE]
<li> [SQLITE_OPEN_EXCLUSIVE]
</ul>
The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
deleted when it is closed. This will always be set for TEMP
databases and journals and for subjournals. The
[SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened
for exclusive access. This flag is set for all files except
for the main database file.
The [sqlite3_file] structure passed as the third argument to
xOpen is allocated by the caller. xOpen just fills it in. The
caller allocates a minimum of szOsFile bytes for the [sqlite3_file]
structure.
}
PARAGRAPH {
The differences between an [SQLITE_OPEN_TEMP_DB] database and an
[SQLITE_OPEN_TRANSIENT_DB] database is this: The [SQLITE_OPEN_TEMP_DB]
is used for explicitly declared and named TEMP tables (using the
CREATE TEMP TABLE syntax) or for named tables in a temporary database
that is created by opening a database with a filename that is an empty
string. An [SQLITE_OPEN_TRANSIENT_DB] holds an database table that
SQLite creates automatically in order to evaluate a subquery or
ORDER BY or GROUP BY clause. Both TEMP_DB and TRANSIENT_DB databases
are private and are deleted automatically. TEMP_DB databases last
for the duration of the database connection. TRANSIENT_DB databases
last only for the duration of a single SQL statement.
}
PARAGRAPH {
The xDelete method is used delete a file. The name of the file is
given in the second parameter. The filename will be in UTF-8.
The VFS must convert the filename into whatever character representation
the underlying operating system expects. If the syncDir parameter is
true, then the xDelete method should not return until the change
to the directory contents for the directory containing the
deleted file have been synced to disk in order to insure that the
file does not "reappear" if a power failure occurs soon after.
}
PARAGRAPH {
The xAccess method is used to check for access permissions on a file.
The filename will be UTF-8 encoded. The flags argument will be
[SQLITE_ACCESS_EXISTS] to check for the existence of the file,
[SQLITE_ACCESS_READWRITE] to check to see if the file is both readable
and writable, or [SQLITE_ACCESS_READ] to check to see if the file is
at least readable. The "file" named by the second parameter might
be a directory or folder name.
}
PARAGRAPH {
The xGetTempName method computes the name of a temporary file that
SQLite can use. The name should be written into the buffer given
by the second parameter. SQLite will size that buffer to hold
at least mxPathname bytes. The generated filename should be in UTF-8.
To avoid security problems, the generated temporary filename should
contain enough randomness to prevent an attacker from guessing the
temporary filename in advance.
}
PARAGRAPH {
The xFullPathname method is used to convert a relative pathname
into a full pathname. The resulting full pathname is written into
the buffer provided by the third parameter. SQLite will size the
output buffer to at least mxPathname bytes. Both the input and
output names should be in UTF-8.
}
PARAGRAPH {
The xDlOpen, xDlError, xDlSym, and xDlClose methods are all used for
accessing shared libraries at run-time. These methods may be omitted
(and their pointers set to zero) if the library is compiled with
SQLITE_OMIT_LOAD_EXTENSION or if the [sqlite3_enable_load_extension()]
interface is never used to enable dynamic extension loading. The
xDlOpen method opens a shared library or DLL and returns a pointer to
a handle. NULL is returned if the open fails. If the open fails,
the xDlError method can be used to obtain a text error message.
The message is written into the zErrMsg buffer of the third parameter
which is at least nByte bytes in length. The xDlSym returns a pointer
to a symbol in the shared library. The name of the symbol is given
by the second parameter. UTF-8 encoding is assumed. If the symbol
is not found a NULL pointer is returned. The xDlClose routine closes
the shared library.
}
PARAGRAPH {
The xRandomness method is used exactly once to initialize the
pseudo-random number generator (PRNG) inside of SQLite. Only
the xRandomness method on the default VFS is used. The xRandomness
methods on other VFSes are never accessed by SQLite.
The xRandomness routine requests that nByte bytes of randomness
be written into zOut. The routine returns the actual number of
bytes of randomness obtained. The quality of the randomness so obtained
will determine the quality of the randomness generated by built-in
SQLite functions such as random() and randomblob(). SQLite also
uses its PRNG to generate temporary file names.. On some platforms
(ex: windows) SQLite assumes that temporary file names are unique
without actually testing for collisions, so it is important to have
good-quality randomness even if the random() and randomblob()
functions are never used.
}
PARAGRAPH {
The xSleep method is used to suspend the calling thread for at
least the number of microseconds given. This method is used to
implement the [sqlite3_sleep()] and [sqlite3_busy_timeout()] APIs.
In the case of [sqlite3_sleep()] the xSleep method of the default
VFS is always used. If the underlying system does not have a
microsecond resolution sleep capability, then the sleep time should
be rounded up. xSleep returns this rounded-up value.
}
PARAGRAPH {
The xCurrentTime method finds the current time and date and writes
the result as double-precision floating point value into pointer
provided by the second parameter. The time and date is in
coordinated universal time (UTC) and is a fractional julian day number.
}
HEADING 3 {The Open File Object}
PARAGRAPH {
The result of opening a file is an instance of an [sqlite3_file] object.
The [sqlite3_file] object is an abstract base class defined as follows:
}
CODE {
typedef struct sqlite3_file sqlite3_file;
struct sqlite3_file {
const struct sqlite3_io_methods *pMethods;
};
}
PARAGRAPH {
Each VFS implementation will subclass the [sqlite3_file] by adding
additional fields at the end to hold whatever information the VFS
needs to know about an open file. It does not matter what information
is stored as long as the total size of the structure does not exceed
the szOsFile value recorded in the [sqlite3_vfs] object.
}
PARAGRAPH {
The [sqlite3_io_methods] object is a structure that contains pointers
to methods for reading, writing, and otherwise dealing with files.
This object is defined as follows:
}
CODE {
typedef struct sqlite3_io_methods sqlite3_io_methods;
struct sqlite3_io_methods {
int iVersion;
int (*xClose)(sqlite3_file*);
int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
int (*xSync)(sqlite3_file*, int flags);
int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
int (*xLock)(sqlite3_file*, int);
int (*xUnlock)(sqlite3_file*, int);
int (*xCheckReservedLock)(sqlite3_file*);
int (*xFileControl)(sqlite3_file*, int op, void *pArg);
int (*xSectorSize)(sqlite3_file*);
int (*xDeviceCharacteristics)(sqlite3_file*);
/* Additional methods may be added in future releases */
};
}
PARAGRAPH {
The iVersion field of [sqlite3_io_methods] is provided as insurance
against future enhancements. The iVersion value should always be
1 for SQLite version 3.5.
}
PARAGRAPH {
The xClose method closes the file. The space for the [sqlite3_file]
structure is deallocated by the caller. But if the [sqlite3_file]
contains pointers to other allocated memory or resources, those
allocations should be released by the xClose method.
}
PARAGRAPH {
The xRead method reads iAmt bytes from the file beginning at a byte
offset to iOfst. The data read is stored in the pointer of the
second parameter. xRead returns the [SQLITE_OK] on success,
[SQLITE_IOERR_SHORT_READ] if it was not able to read the full number
of bytes because it reached end-of-file, or [SQLITE_IOERR_READ] for
any other error.
}
PARAGRAPH {
The xWrite method writes iAmt bytes of data from the second parameter
into the file beginning at an offset of iOfst bytes. If the size of
the file is less than iOfst bytes prior to the write, then xWrite should
ensure that the file is extended with zeros up to iOfst bytes prior
to beginning its write. xWrite continues to extends the file as
necessary so that the size of the file is at least iAmt+iOfst bytes
at the conclusion of the xWrite call. The xWrite method returns
[SQLITE_OK] on success. If the write cannot complete because the
underlying storage medium is full, then [SQLITE_FULL] is returned.
[SQLITE_IOERR_WRITE] should be returned for any other error.
}
PARAGRAPH {
The xTruncate method truncates a file to be nByte bytes in length.
If the file is already nByte bytes or less in length then this
method is a no-op. The xTruncate method returns [SQLITE_OK] on
success and [SQLITE_IOERR_TRUNCATE] if anything goes wrong.
}
PARAGRAPH {
The xSync method is used to force previously written data out of
operating system cache and into non-volatile memory. The second
parameter is usually [SQLITE_SYNC_NORMAL]. If the second parameter
is [SQLITE_SYNC_FULL] then the xSync method should make sure that
data has also been flushed through the disk controllers cache.
The [SQLITE_SYNC_FULL] parameter is the equivalent of the F_FULLSYNC
ioctl() on Mac OS X. The xSync method returns
[SQLITE_OK] on success and [SQLITE_IOERR_FSYNC] if anything goes wrong.
}
PARAGRAPH {
The xFileSize() method determines the current size of the file
in bytes and writes that value into *pSize. It returns [SQLITE_OK]
on success and [SQLITE_IOERR_FSTAT] if something goes wrong.
}
PARAGRAPH {
The xLock and xUnlock methods are used to set and clear file locks.
SQLite supports five levels of file locks, in order:
<ul>
<li> [SQLITE_LOCK_NONE]
<li> [SQLITE_LOCK_SHARED]
<li> [SQLITE_LOCK_RESERVED]
<li> [SQLITE_LOCK_PENDING]
<li> [SQLITE_LOCK_EXCLUSIVE]
</ul>
The underlying implementation can support some subset of these locking
levels as long as it meets the other requirements of this paragraph.
The locking level is specified as the second argument to both xLock
and xUnlock. The xLock method increases the locking level to the
specified locking level or higher. The xUnlock method decreases the
locking level to no lower than the level specified.
[SQLITE_LOCK_NONE] means that the file is unlocked. [SQLITE_LOCK_SHARED]
gives permission to read the file. Multiple database connections can
hold [SQLITE_LOCK_SHARED] at the same time.
[SQLITE_LOCK_RESERVED] is like [SQLITE_LOCK_SHARED] in that its is permission
to read the file. But only a single connection can hold a reserved lock
at any point in time. The [SQLITE_LOCK_PENDING] is also permission to
read the file. Other connections can continue to read the file as well,
but no other connection is allowed to escalate a lock from none to shared.
[SQLITE_LOCK_EXCLUSIVE] is permission to write on the file. Only a single
connection can hold an exclusive lock and no other connection can hold
any lock (other than "none") while one connection is hold an exclusive
lock. The xLock returns [SQLITE_OK] on success, [SQLITE_BUSY] if it
is unable to obtain the lock, or [SQLITE_IOERR_RDLOCK] if something else
goes wrong. The xUnlock method returns [SQLITE_OK] on success and
[SQLITE_IOERR_UNLOCK] for problems.
}
PARAGRAPH {
The xCheckReservedLock method checks to see if another connection or
another process is currently holding a reserved, pending, or exclusive
lock on the file. It returns true or false.
}
PARAGRAPH {
The xFileControl() method is a generic interface that allows custom
VFS implementations to directly control an open file using the
(new and experimental)
[sqlite3_file_control()] interface. The second "op" argument
is an integer opcode. The third
argument is a generic pointer which is intended to be a pointer
to a structure that may contain arguments or space in which to
write return values. Potential uses for xFileControl() might be
functions to enable blocking locks with timeouts, to change the
locking strategy (for example to use dot-file locks), to inquire
about the status of a lock, or to break stale locks. The SQLite
core reserves opcodes less than 100 for its own use.
A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
Applications that define a custom xFileControl method should use opcodes
greater than 100 to avoid conflicts.
}
PARAGRAPH {
The xSectorSize returns the "sector size" of the underlying
non-volatile media. A "sector" is defined as the smallest unit of
storage that can be written without disturbing adjacent storage.
On a disk drive the "sector size" has until recently been 512 bytes,
though there is a push to increase this value to 4KiB. SQLite needs
to know the sector size so that it can write a full sector at a
time, and thus avoid corrupting adjacent storage space if a power
lose occurs in the middle of a write.
}
PARAGRAPH {
The xDeviceCharacteristics method returns an integer bit vector that
defines any special properties that the underlying storage medium might
have that SQLite can use to increase performance. The allowed return
is the bit-wise OR of the following values:
<ul>
<li> [SQLITE_IOCAP_ATOMIC]
<li> [SQLITE_IOCAP_ATOMIC512]
<li> [SQLITE_IOCAP_ATOMIC1K]
<li> [SQLITE_IOCAP_ATOMIC2K]
<li> [SQLITE_IOCAP_ATOMIC4K]
<li> [SQLITE_IOCAP_ATOMIC8K]
<li> [SQLITE_IOCAP_ATOMIC16K]
<li> [SQLITE_IOCAP_ATOMIC32K]
<li> [SQLITE_IOCAP_ATOMIC64K]
<li> [SQLITE_IOCAP_SAFE_APPEND]
<li> [SQLITE_IOCAP_SEQUENTIAL]
</ul>
The [SQLITE_IOCAP_ATOMIC] bit means that all writes to this device are
atomic in the sense that either the entire write occurs or none of it
occurs. The other
[SQLITE_IOCAP_ATOMIC | SQLITE_IOCAP_ATOMIC<i>nnn</i>] values indicate that
writes of aligned blocks of the indicated size are atomic.
[SQLITE_IOCAP_SAFE_APPEND] means that when extending a file with new
data, the new data is written first and then the file size is updated.
So if a power failure occurs, there is no chance that the file might have
been extended with randomness. The [SQLITE_IOCAP_SEQUENTIAL] bit means
that all writes occur in the order that they are issued and are not
reordered by the underlying file system.
}
HEADING 3 {Checklist For Constructing A New VFS}
PARAGRAPH {
The preceding paragraphs contain a lot of information.
To ease the task of constructing
a new VFS for SQLite we offer the following implementation checklist:
}
PARAGRAPH {
<ol>
<li> Define an appropriate subclass of the [sqlite3_file] object.
<li> Implement the methods required by the [sqlite3_io_methods] object.
<li> Create a static and
constant [sqlite3_io_methods] object containing pointers
to the methods from the previous step.
<li> Implement the xOpen method that opens a file and populates an
[sqlite3_file] object, including setting pMethods to
point to the [sqlite3_io_methods] object from the previous step.
<li> Implement the other methods required by [sqlite3_vfs].
<li> Define a static (but not constant) [sqlite3_vfs] structure that
contains pointers to the xOpen method and the other methods and
which contains the appropriate values for iVersion, szOsFile,
mxPathname, zName, and pAppData.
<li> Implement a procedure that calls [sqlite3_vfs_register()] and
passes it a pointer to the [sqlite3_vfs] structure from the previous
step. This procedure is probably the only exported symbol in the
source file that implements your VFS.
</ol>
}
PARAGRAPH {
Within your application, call the procedure implemented in the last
step above as part of your initialization process before any
database connections are opened.
}
HEADING 1 {The Memory Allocation Subsystem}
PARAGRAPH {
Beginning with version 3.5, SQLite obtains all of the heap memory it
needs using the routines [sqlite3_malloc()], [sqlite3_free()], and
[sqlite3_realloc()]. These routines have existed in prior versions
of SQLite, but SQLite has previously bypassed these routines and used
its own memory allocator. This all changes in version 3.5.0.
}
PARAGRAPH {
The SQLite source tree actually contains multiple versions of the
memory allocator. The default high-speed version found in the
"mem1.c" source file is used for most builds. But if the SQLITE_MEMDEBUG
flag is enabled, a separate memory allocator the "mem2.c" source file
is used instead. The mem2.c allocator implements lots of hooks to
do error checking and to simulate memory allocation failures for testing
purposes. Both of these allocators use the malloc()/free() implementation
in the standard C library.
}
PARAGRAPH {
Applications are not required to use either of these standard memory
allocators. If SQLite is compiled with SQLITE_OMIT_MEMORY_ALLOCATION
then no implementation for the [sqlite3_malloc()], [sqlite3_realloc()],
and [sqlite3_free()] functions is provided. Instead, the application
that links against SQLite must provide its own implementation of these
functions. The application provided memory allocator is not required
to use the malloc()/free() implementation in the standard C library.
An embedded application might provide an alternative memory allocator
that uses memory for a fixed memory pool set aside for the exclusive
use of SQLite, for example.
}
PARAGRAPH {
Applications that implement their own memory allocator must provide
implementation for the usual three allocation functions
[sqlite3_malloc()], [sqlite3_realloc()], and [sqlite3_free()].
And they must also implement a fourth function:
}
CODE {
int sqlite3_memory_alarm(
void(*xCallback)(void *pArg, sqlite3_int64 used, int N),
void *pArg,
sqlite3_int64 iThreshold
);
}
PARAGRAPH {
The [sqlite3_memory_alarm] routine is used to register
a callback on memory allocation events.
This routine registers or clears a callbacks that fires when
the amount of memory allocated exceeds iThreshold. Only
a single callback can be registered at a time. Each call
to [sqlite3_memory_alarm()] overwrites the previous callback.
The callback is disabled by setting xCallback to a NULL
pointer.
}
PARAGRAPH {
The parameters to the callback are the pArg value, the
amount of memory currently in use, and the size of the
allocation that provoked the callback. The callback will
presumably invoke [sqlite3_free()] to free up memory space.
The callback may invoke [sqlite3_malloc()] or [sqlite3_realloc()]
but if it does, no additional callbacks will be invoked by
the recursive calls.
}
PARAGRAPH {
The [sqlite3_soft_heap_limit()] interface works by registering
a memory alarm at the soft heap limit and invoking
[sqlite3_release_memory()] in the alarm callback. Application
programs should not attempt to use the [sqlite3_memory_alarm()]
interface because doing so will interfere with the
[sqlite3_soft_heap_limit()] module. This interface is exposed
only so that applications can provide their own
alternative implementation when the SQLite core is
compiled with SQLITE_OMIT_MEMORY_ALLOCATION.
}
PARAGRAPH {
The built-in memory allocators in SQLite also provide the following
additional interfaces:
}
CODE {
sqlite3_int64 sqlite3_memory_used(void);
sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
}
PARAGRAPH {
These interfaces can be used by an application to monitor how
much memory SQLite is using. The [sqlite3_memory_used()] routine
returns the number of bytes of memory currently in use and the
[sqlite3_memory_highwater()] returns the maximum instantaneous
memory usage. Neither routine includes the overhead associated
with the memory allocator. These routines are provided for use
by the application. SQLite never invokes them itself. So if
the application is providing its own memory allocation subsystem,
it can omit these interfaces if desired.
}
HEADING 1 {The Mutex Subsystem}
PARAGRAPH {
SQLite has always been threadsafe in the sense that it is safe to
use different SQLite database connections in different threads at the
same time. The constraint was that the same database connection
could not be used in two separate threads at once. SQLite version 3.5.0
relaxes this constraint.
}
PARAGRAPH {
In order to allow multiple threads to use the same database connection
at the same time, SQLite must make extensive use of mutexes. And for
this reason a new mutex subsystem as been added. The mutex subsystem
as the following interface:
}
CODE {
sqlite3_mutex *sqlite3_mutex_alloc(int);
void sqlite3_mutex_free(sqlite3_mutex*);
void sqlite3_mutex_enter(sqlite3_mutex*);
int sqlite3_mutex_try(sqlite3_mutex*);
void sqlite3_mutex_leave(sqlite3_mutex*);
}
PARAGRAPH {
Though these routines exist for the use of the SQLite core,
application code is free to use these routines as well, if desired.
A mutex is an [sqlite3_mutex] object. The [sqlite3_mutex_alloc()]
routine allocates a new mutex object and returns a pointer to it.
The argument to [sqlite3_mutex_alloc()] should be
[SQLITE_MUTEX_FAST] or [SQLITE_MUTEX_RECURSIVE] for non-recursive
and recursive mutexes, respectively. If the underlying system does
not provide non-recursive mutexes, then a recursive mutex can be
substituted in that case. The argument to [sqlite3_mutex_alloc()]
can also be a constant designating one of several static mutexes:
<ul>
<li> [SQLITE_MUTEX_STATIC_MASTER]
<li> [SQLITE_MUTEX_STATIC_MEM]
<li> [SQLITE_MUTEX_STATIC_MEM2]
<li> [SQLITE_MUTEX_STATIC_PRNG]
<li> [SQLITE_MUTEX_STATIC_LRU]
</ul>
These static mutexes are reserved for use internally by SQLite
and should not be used by the application. The static mutexes
are all non-recursive.
}
PARAGRAPH {
The [sqlite3_mutex_free()] routine should be used to deallocate
a non-static mutex. If a static mutex is passed to this routine
then the behavior is undefined.
}
PARAGRAPH {
The [sqlite3_mutex_enter()] attempts to enter the mutex and blocks
if another threads is already there. [sqlite3_mutex_try()] attempts
to enter and returns [SQLITE_OK] on success or [SQLITE_BUSY] if another
thread is already there. [sqlite3_mutex_leave()] exits a mutex.
The mutex is held until the number of exits matches the number of
entrances. If [sqlite3_mutex_leave()] is called on a mutex that
the thread is not currently holding, then the behavior is undefined.
If any routine is called for a deallocated mutex, then the behavior
is undefined.
}
PARAGRAPH {
The SQLite source code provides multiple implementations of these
APIs, suitable for varying environments. If SQLite is compiled with
the SQLITE_THREADSAFE=0 flag then a no-op mutex implementation that
is fast but does no real mutual exclusion is provided. That
implementation is suitable for use in single-threaded applications
or applications that only use SQLite in a single thread. Other
real mutex implementations are provided based on the underlying
operating system.
}
PARAGRAPH {
Embedded applications may wish to provide their own mutex implementation.
If SQLite is compiled with the -DSQLITE_MUTEX_APPDEF=1 compile-time flag
then the SQLite core provides no mutex subsystem and a mutex subsystem
that matches the interface described above must be provided by the
application that links against SQLite.
}
HEADING 1 {Other Interface Changes}
PARAGRAPH {
Version 3.5.0 of SQLite changes the behavior of a few APIs in ways
that are technically incompatible. However, these APIs are seldom
used and even when they are used it is difficult to imagine a
scenario where the change might break something. The changes
actually makes these interface much more useful and powerful.
}
PARAGRAPH {
Prior to version 3.5.0, the [sqlite3_enable_shared_cache()] API
would enable and disable the shared cache feature for all connections
within a single thread - the same thread from which the
sqlite3_enable_shared_cache() routine was called. Database connections
that used the shared cache were restricted to running in the same
thread in which they were opened. Beginning with version 3.5.0,
the sqlite3_enable_shared_cache() applies to all database connections
in all threads within the process. Now database connections running
in separate threads can share a cache. And database connections that
use shared cache can migrate from one thread to another.
}
PARAGRAPH {
Prior to version 3.5.0 the [sqlite3_soft_heap_limit()] set an upper
bound on heap memory usage for all database connections within a
single thread. Each thread could have its own heap limit. Beginning
in version 3.5.0, there is a single heap limit for the entire process.
This seems more restrictive (one limit as opposed to many) but in
practice it is what most users want.
}
PARAGRAPH {
Prior to version 3.5.0 the [sqlite3_release_memory()] function would
try to reclaim memory from all database connections in the same thread
as the sqlite3_release_memory() call. Beginning with version 3.5.0,
the sqlite3_release_memory() function will attempt to reclaim memory
from all database connections in all threads.
}
HEADING 1 {Summary}
PARAGRAPH {
The transition from SQLite version 3.4.2 to 3.5.0 is a major change.
Every source code file in the SQLite core had to be modified, some
extensively. And the change introduced some minor incompatibilities
in the C interface. But we feel that the benefits of the transition
from 3.4.2 to 3.5.0 far outweigh the pain of porting. The new
VFS layer is now well-defined and stable and should simplify future
customizations. The VFS layer, and the separable memory allocator
and mutex subsystems allow a standard SQLite source code amalgamation
to be used in an embedded project without change, greatly simplifying
configuration management. And the resulting system is much more
tolerant of highly threaded designs.
}