From 50d3f9064bc7bfd95d6a19b1a9797ee9d12f7769 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 27 Aug 2007 21:10:36 +0000 Subject: [PATCH] Added the 34to35.html document describing the changes between 3.4.2 and 3.5.0. Minor interface cleanups. (CVS 4302) FossilOrigin-Name: 0791f917bb18d7305b805b9cbcb308bdd7b3a1f5 --- main.mk | 6 +- manifest | 23 +- manifest.uuid | 2 +- src/os_unix.c | 2 +- src/os_win.c | 4 +- src/sqlite.h.in | 26 +- src/test_async.c | 4 +- www/34to35.tcl | 966 +++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 1007 insertions(+), 26 deletions(-) create mode 100644 www/34to35.tcl diff --git a/main.mk b/main.mk index f0bf6ef49e..5ff4fb2f76 100644 --- a/main.mk +++ b/main.mk @@ -707,6 +707,9 @@ version3.html: $(TOP)/www/version3.tcl whentouse.html: $(TOP)/www/whentouse.tcl tclsh $(TOP)/www/whentouse.tcl >whentouse.html +34to35.html: $(TOP)/www/34to35.tcl + tclsh $(TOP)/www/34to35.tcl >34to35.html + # Files to be published on the website. # @@ -750,7 +753,8 @@ DOC = \ tclsqlite.html \ vdbe.html \ version3.html \ - whentouse.html + whentouse.html \ + 34to35.html doc: common.tcl $(DOC) mkdir -p doc diff --git a/manifest b/manifest index 90c16bc398..97f8b9459f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\ssqlite3_release_memory()\sto\suse\sa\sglobal\sLRU\slist\sof\spages.\sUntested.\s(CVS\s4301) -D 2007-08-27T17:27:49 +C Added\sthe\s34to35.html\sdocument\sdescribing\sthe\schanges\sbetween\s3.4.2\sand\n3.5.0.\s\sMinor\sinterface\scleanups.\s(CVS\s4302) +D 2007-08-27T21:10:36 F Makefile.in 938f2769921fa1b30c633548f153804021eb1512 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -63,7 +63,7 @@ F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33 F ext/icu/icu.c 61a345d8126686aa3487aa8d2d0f68abd655f7a4 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 56abb507100ed2d4261f6dd1653dec3cf4066387 -F main.mk 9e796bb4e04ca16d3d1506e6496a7468410dd441 +F main.mk 238b00009433760c469ceb94f37f49e76dceae45 F mkdll.sh 37fa8a7412e51b5ab2bc6d4276135f022a0feffb F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 1a866b53637dab137191341cc875575a5ca110fb @@ -111,9 +111,9 @@ F src/os_os2.c 8769301bff502de642ad2634cedcb77d967ce199 F src/os_os2.h c3f7d0af7e3453d1d7aa81b06c0a56f5a226530b F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3 -F src/os_unix.c 27b1fad58587bc949013a5a4df9fc20fce395648 +F src/os_unix.c 7a340c712efa1bde95b6e23b7f279d9fb6e7dcf2 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e -F src/os_win.c 4f840e97624dbde9cae3d020ce072a4f1d2a11b1 +F src/os_win.c 3ffd3aacff4cb69848284e29dcec0feff23b0752 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c cfa6dc38b797206549491de3ec7f0aea50611dda F src/pager.h 53087c6fb9db01aed17c7fd044662a27507e89b8 @@ -125,7 +125,7 @@ F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da F src/select.c 98c367bce3f38c5adfcc97de9ab5c79b0e5dc2b2 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb -F src/sqlite.h.in 2d45cd3fc1b6677d06c8e547bbe1b9a040a7f677 +F src/sqlite.h.in 4cf42ce749e4bdf13b9bb4959e91439c3ce8a054 F src/sqlite3ext.h 9a26028378c288af500d8b94ed079666fed5806b F src/sqliteInt.h 13c908f5f156a192fcd247f993ac513bfaf81f53 F src/sqliteLimit.h 1bcbbdfa856f8b71b561abb31edb864b0eca1d12 @@ -140,7 +140,7 @@ F src/test6.c a6223d9d938aba83f20611a2c01680d8043cd2f7 F src/test7.c a9d509d0e9ad214b4772696f49f6e61be26213d1 F src/test8.c a91b8d28341bbd168f5ba1ecad2be1008ddf15d1 F src/test9.c b46c8fe02ac7cca1a7316436d8d38d50c66f4b2f -F src/test_async.c 12ff3db0e052f561596d4dbdd29272f28b25060d +F src/test_async.c f222bd196b55a2e73b1427400d5aa97841787167 F src/test_autoext.c 855157d97aa28cf84233847548bfacda21807436 F src/test_btree.c c1308ba0b88ab577fa56c9e493a09829dfcded9c F src/test_config.c f0b911bb615d93a192647e76910dce65cbbcf3ad @@ -504,6 +504,7 @@ F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b F tool/spaceanal.tcl f60a242a996a79d59cad6615cec83a9203e17911 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff +F www/34to35.tcl 5a477bf9210b324ee16bd26fc04ddd578b63b395 F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf F www/arch.gif f845a64772062e82d17980a349f95f1f0b4c8054 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4 @@ -561,7 +562,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 3d746343add3feb9d208302a00b419d71d6ba246 -R 95f58c79a104b4b1aa01178fe78f1fa0 -U danielk1977 -Z 8ec1ffcae0650e586d1badb059ab31f9 +P 5626ce0b5e249d48b56fdc4561ef663941eb23dc +R 53f45ea77bc4d4516f85c7437592148c +U drh +Z edf7af5b96ec397985d0784a02a0916d diff --git a/manifest.uuid b/manifest.uuid index ba5f676f17..350afa3baf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5626ce0b5e249d48b56fdc4561ef663941eb23dc \ No newline at end of file +0791f917bb18d7305b805b9cbcb308bdd7b3a1f5 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index e9150f1df9..1b23fef1ef 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -2463,7 +2463,7 @@ static int unixAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ case SQLITE_ACCESS_READWRITE: amode = W_OK|R_OK; break; - case SQLITE_ACCESS_READONLY: + case SQLITE_ACCESS_READ: amode = R_OK; break; diff --git a/src/os_win.c b/src/os_win.c index e87c416490..36cce4f87c 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -1237,15 +1237,13 @@ static int winAccess( } free(zConverted); switch( flags ){ + case SQLITE_ACCESS_READ: case SQLITE_ACCESS_EXISTS: rc = attr!=0xffffffff; break; case SQLITE_ACCESS_READWRITE: rc = (attr & FILE_ATTRIBUTE_READONLY)==0; break; - case SQLITE_ACCESS_READONLY: - rc = (attr!=0xffffffff) && ((attr & FILE_ATTRIBUTE_READONLY)==1); - break; default: assert(!"Invalid flags argument"); } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index edbffc8eb6..3b1af5e9cc 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.243 2007/08/27 17:27:49 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.244 2007/08/27 21:10:36 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -553,7 +553,7 @@ typedef struct sqlite3_mutex sqlite3_mutex; ** 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 +** 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 @@ -599,10 +599,10 @@ typedef struct sqlite3_mutex sqlite3_mutex; ** 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. +** Space to hold the [sqlite3_file] structure passed as the third +** argument to xOpen is allocated by caller (the SQLite core). +** szOsFile bytes are allocated for this object. The xOpen method +** fills in the allocated space. ** ** The flags argument to xAccess() may be 0 (to test for the ** existance of a file) or SQLITE_ACCESS_READWRITE to test to see @@ -649,9 +649,21 @@ struct sqlite3_vfs { ** value will increment whenever this happens. */ }; +/* +** CAPI3REF: Flags for the xAccess VFS method +** +** These integer constants can be used as the third parameter to +** the xAccess method of an [sqlite3_vfs] object. They determine +** the kind of what kind of permissions the xAccess method is +** looking for. With SQLITE_ACCESS_EXISTS, the xAccess method +** simply checks to see if the file exists. With SQLITE_ACCESS_READWRITE, +** the xAccess method checks to see if the file is both readable +** and writable. With SQLITE_ACCESS_READ the xAccess method +** checks to see if the file is readable. +*/ #define SQLITE_ACCESS_EXISTS 0 #define SQLITE_ACCESS_READWRITE 1 -#define SQLITE_ACCESS_READONLY 2 +#define SQLITE_ACCESS_READ 2 /* ** CAPI3REF: Enable Or Disable Extended Result Codes diff --git a/src/test_async.c b/src/test_async.c index 572620c69c..1627f912fa 100644 --- a/src/test_async.c +++ b/src/test_async.c @@ -726,7 +726,7 @@ static int asyncAccess(sqlite3_vfs *pAsyncVfs, const char *zName, int flags){ sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; assert(flags==SQLITE_ACCESS_READWRITE - || flags==SQLITE_ACCESS_READONLY + || flags==SQLITE_ACCESS_READ || flags==SQLITE_ACCESS_EXISTS ); @@ -745,7 +745,7 @@ static int asyncAccess(sqlite3_vfs *pAsyncVfs, const char *zName, int flags){ } ASYNC_TRACE(("ACCESS(%s): %s = %d\n", flags==SQLITE_ACCESS_READWRITE?"read-write": - flags==SQLITE_ACCESS_READONLY?"read-only":"exists" + flags==SQLITE_ACCESS_READ?"read":"exists" , zName, ret) ); pthread_mutex_unlock(&async.queueMutex); diff --git a/www/34to35.tcl b/www/34to35.tcl new file mode 100644 index 0000000000..83c8c12f69 --- /dev/null +++ b/www/34to35.tcl @@ -0,0 +1,966 @@ +# +# Run this TCL script to generate HTML for the goals.html file. +# +set rcsid {$Id: 34to35.tcl,v 1.1 2007/08/27 21:10:36 drh Exp $} +source common.tcl +header {SQLite Changes From Version 3.4.2 To 3.5.0} + +proc CODE {text} { + puts "
"
+  puts $text
+  puts "
" +} +proc SYNTAX {text} { + puts "
"
+  set t2 [string map {& & < < > >} $text]
+  regsub -all "/(\[^\n/\]+)/" $t2 {\1} t3
+  puts "$t3"
+  puts "
" +} +proc IMAGE {name {caption {}}} { + puts "
" + if {$caption!=""} { + puts "
$caption" + } + puts "
" +} +proc PARAGRAPH {text} { + # regsub -all "/(\[a-zA-Z0-9\]+)/" $text {\1} t2 + #regsub -all "\\*(\[^\n*\]+)\\*" $text {\1} t3 + regsub -all {\[([^]\n]+)\]} $text {\1} t3 + puts "

$t3

\n" +} +set level(0) 0 +set level(1) 0 +proc HEADING {n name {tag {}}} { + if {$tag!=""} { + puts "" + } + 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 "$num $name" +} + +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 { +
    +
  1. The OS interface layer has been completely reworked: +
      +
    1. The [sqlite3_os_switch()] interface has been removed.
    2. +
    3. The [SQLITE_ENABLE_REDEF_IO] compile-time flag no longer functions. + I/O procedures are now always redefinable.
    4. +
    5. Three new objects are defined for specifying I/O procedures: + [sqlite3_vfs], [sqlite3_file], and [sqlite3_io_methods].
    6. +
    7. Three new interfaces are used to create alternative OS interfaces: + [sqlite3_vfs_register()], [sqlite3_vfs_unregister()], and + [sqlite3_vfs_find()].
    8. +
    9. 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.
    10. +
  2. +
  3. 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. +
      +
    1. 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.
    2. +
    3. 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.
    4. +
    5. 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.
    6. +
    7. The [sqlite3_thread_cleanup()] interface has become a no-op.
    8. +
  4. +
  5. 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.
  6. +
  7. 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.
  8. +
  9. There is now a compile-time option that allows an application to + define alternative mutex implementations without having + to modify any core SQLite code.
  10. +
+} +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) [sqlite3_os_switch()] + 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: +
    +
  • [SQLITE_OPEN_MAIN_DB] +
  • [SQLITE_OPEN_MAIN_JOURNAL] +
  • [SQLITE_OPEN_TEMP_DB] +
  • [SQLITE_OPEN_TEMP_JOURNAL] +
  • [SQLITE_OPEN_SUBJOURNAL] +
  • [SQLITE_OPEN_MASTER_JOURNAL] +
+ 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 return 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: +
    +
  • [SQLITE_OPEN_DELETEONCLOSE] +
  • [SQLITE_OPEN_EXCLUSIVE] +
+ 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 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 once by the first database connection + that is opened. xRandomness should return high-quality randomness + that SQLite will used to seeds its internal pseudo-random number + generator (PRNG). The 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(). +} + +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, sqlite_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*); + int (*xBreakLock)(sqlite3_file*); + int (*xLockState)(sqlite3_file *); + 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 SQLITE_SYNC_BARRIER is currently unused. + In the future this value might request that the xSync call serve + as an I/O barrier operation. All write requests that occur before + the xSync must complete before any write request that occurs + afterwards, but the barrier does not require that all writes + complete prior to the return of xSync. 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: +
    +
  • [SQLITE_LOCK_NONE] +
  • [SQLITE_LOCK_SHARED] +
  • [SQLITE_LOCK_RESERVED] +
  • [SQLITE_LOCK_PENDING] +
  • [SQLITE_LOCK_EXCLUSIVE] +
+ 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 xLockState method returns one of the [SQLITE_LOCK_NONE] through + [SQLITE_LOCK_EXCLUSIVE] constants defined above to indicate the current + state of the lock for the given file handle. This method is used for + testing purposes only. +} + +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: +
    +
  • SQLITE_IOCAP_ATOMIC +
  • SQLITE_IOCAP_ATOMIC512 +
  • SQLITE_IOCAP_ATOMIC1K +
  • SQLITE_IOCAP_ATOMIC2K +
  • SQLITE_IOCAP_ATOMIC4K +
  • SQLITE_IOCAP_ATOMIC8K +
  • SQLITE_IOCAP_ATOMIC16K +
  • SQLITE_IOCAP_ATOMIC32K +
  • SQLITE_IOCAP_ATOMIC64K +
  • SQLITE_IOCAP_SAFE_APPEND +
  • SQLITE_IOCAP_SEQUENTIAL +
+ 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_ATOMICnnn 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 { +
    +
  1. Define an appropriate subclass of the [sqlite3_file] object. +
  2. Implement the methods required by the [sqlite_io_methods] object. +
  3. Create a static and + constant [sqlite3_io_methods] object containing pointers + to the methods from the previous step. +
  4. 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. +
  5. Implement the other methods required by [sqlite3_vfs]. +
  6. 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. +
  7. 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. +
+} + +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: +
    +
  • SQLITE_MUTEX_STATIC_MASTER +
  • SQLITE_MUTEX_STATIC_MEM +
  • SQLITE_MUTEX_STATIC_MEM2 +
  • SQLITE_MUTEX_STATIC_PRNG +
+ 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. +}