diff --git a/Makefile.in b/Makefile.in
index 7b7de54fb0..fdfe635666 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -226,6 +226,7 @@ sqlite.tar.gz:
pwd=`pwd`; cd $(TOP)/..; tar czf $$pwd/sqlite.tar.gz sqlite
index.html: $(TOP)/www/index.tcl sqlite.tar.gz last_change
+ cp ../sqlite-*.tar.gz .
tclsh $(TOP)/www/index.tcl `cat $(TOP)/VERSION` >index.html
sqlite.html: $(TOP)/www/sqlite.tcl
@@ -237,9 +238,6 @@ c_interface.html: $(TOP)/www/c_interface.tcl
changes.html: $(TOP)/www/changes.tcl
tclsh $(TOP)/www/changes.tcl >changes.html
-fileformat.html: $(TOP)/www/fileformat.tcl
- tclsh $(TOP)/www/fileformat.tcl >fileformat.html
-
lang.html: $(TOP)/www/lang.tcl
tclsh $(TOP)/www/lang.tcl >lang.html
@@ -272,7 +270,6 @@ PUBLISH = \
index.html \
sqlite.html \
changes.html \
- fileformat.html \
lang.html \
opcode.html \
arch.html \
@@ -286,8 +283,8 @@ PUBLISH = \
website: $(PUBLISH)
publish: $(PUBLISH)
- chmod 0644 $(PUBLISH)
- scp $(PUBLISH) hwaci@oak.he.net:public_html/sw/sqlite
+ chmod 0644 $(PUBLISH) sqlite-*.tar.gz
+ scp $(PUBLISH) sqlite-*.tar.gz hwaci@oak.he.net:public_html/sw/sqlite
install: sqlite libsqlite.a sqlite.h
mv sqlite /usr/bin
diff --git a/VERSION b/VERSION
index 227cea2156..3b51d04485 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.0
+2.0-alpha-2
diff --git a/manifest b/manifest
index 4ee6e62269..9fb942652c 100644
--- a/manifest
+++ b/manifest
@@ -1,8 +1,8 @@
-C Add\sthe\sOpenReadOnly()\sOS\smethod\sto\sfix\sa\sbug\sin\sthe\spager.\s(CVS\s257)
-D 2001-09-19T13:58:44
-F Makefile.in 1d9592c4aeedd3643b2e1dfa037ce5faf54805a3
+C 2.0-Alpha-2\srelease\s(CVS\s258)
+D 2001-09-20T01:44:43
+F Makefile.in 0af884b48d7dbcd01d73a9d93cb3e19b34c9f087
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
-F VERSION 3861a21803fcd9eb92a403027b0da2bb7add4de1
+F VERSION 6942aa44940d2972bd72f671a631060106e77f7e
F configure aad857a97ca28a584228869186eb4cd7dbebbb3a x
F configure.in 0000c0d62beb47cae1d2d81a197c7fe6efd56a45
F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
@@ -16,9 +16,9 @@ F src/expr.c 343a515a4abaf60e9e26c7412aa8c43fd3eae97d
F src/insert.c b34860ea58525754f18bde652f74161295ca2455
F src/main.c 5e5794eea3316dd3a63c112ccdcc997b9118f345
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
-F src/os.c 43735db052288f8bfee56e09dfa293c202ff93a3
-F src/os.h 6d627d8629a204c474cf13aa098654658378a81f
-F src/pager.c a77c7fd3f33c0c6834a042b9b0d4a8128553532e
+F src/os.c faf9f484f3261c7650021cae79294338491f2cfb
+F src/os.h 0f478e2fef5ec1612f94b59b163d4807d4c77d6d
+F src/pager.c 0fe02b63a89d8eebb42ad30529d0c7cc918ecb94
F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca
F src/parse.y 2bcf47bb8e6afd8bc10aebd555fa07b73905bee4
F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9
@@ -26,7 +26,7 @@ F src/random.c b6a57e85288470b013ad584a8813e893b60e62fe
F src/select.c 7d90a6464906419fde96c0707a4cf4f3280db318
F src/shell.c 8e573138074e0b9526fca59b3eac22bdf18ecc03
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
-F src/sqlite.h.in 689401a6cfb4c2344e67d80fa6bb0d74c87e6e31
+F src/sqlite.h.in 5d78c86bd9a9b8bbba65f860fbaf71c1882d6030
F src/sqliteInt.h 667126497697d58a114d9db492f38c99eadb36d7
F src/table.c abd0adbe0fee39d995287b3bcccd908d174dfcac
F src/tclsqlite.c 04a35d04f06046acc3944121dc6c36717f7f36d5
@@ -55,7 +55,7 @@ F test/main.test 085ece17913a487caacbc0a392638c958c83a75d
F test/malloc.test f1400a8d002eb96f1ca0a34abe56d2ab3e324740
F test/misc1.test 50a5ca3481fc1f3cd6b978bcd6ed04c06f26a1e6
F test/pager.test 59bbc4e3d489529ed33db6e15595789e51056077
-F test/printf.test 93ecd43cc48e863a325560f36c3b2741f5fe0308
+F test/printf.test 3cb415073754cb8ff076f26173143c3cd293a9da
F test/quick.test b6ec50f808efc06595fd324bf4f3fabadb9c7e9c
F test/quote.test 286db944717afa9a9bf829dd85e59185c65d5435
F test/rowid.test 427bfbbe9684fe7a2f851aa05badaae6d4972ce8
@@ -69,7 +69,7 @@ F test/subselect.test 335d3dad8d585726c447dfee8d9c4f7383c76b78
F test/table.test 52fdca1632580fb638c7b7dd14f4d37ecc09f994
F test/tableapi.test 162840153191a91a7dce6395f2334f9aef713b37
F test/tclsqlite.test a57bb478d7e9f0b2c927f92e161f391e2896631a
-F test/tester.tcl 4d93d04bb43c5936f33d30df82d2801b519df74e
+F test/tester.tcl 957cd92fe8645b829da175d94b7ddb7ea68dac39
F test/trans.test 997c8dcc15c479bc2cedc42220cf2d265e63d2a8
F test/update.test b320ea22899e80b32b4d21c54591eb7a6ba4d6bd
F test/vacuum.test 8acf8669f3b627e54149b25165b034aa06c2432e
@@ -81,22 +81,21 @@ F tool/opNames.awk 5ba1f48aa854ee3b7c3d2b54233665bc3e649ea2
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/renumberOps.awk 6d067177ad5f8d711b79577b462da9b3634bd0a9
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
-F www/arch.fig 468adec4c4d7ef70fdc0a9e74e3afc86f440a40f
-F www/arch.png ce828ead98b46684937972aac17cd6569a2feb20
-F www/arch.tcl f5d76cea4feb997c3a474191cbe4fa52c8847ad6
-F www/c_interface.tcl ddca19005c47dd5a15882addc02fff5de83d8ed9
+F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
+F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
+F www/arch.tcl c1891efdc00cd76eec72bdbf8b446195902932a3
+F www/c_interface.tcl 52ae81c89bf906b358e04857bd3f76b1a7f61c1b
F www/changes.tcl 0a791dbf5af35d7adde6fcce8465829d599f000e
F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
-F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9
-F www/index.tcl a9c1bfea2e854856d9cb83a0cf850d657cd92588
-F www/lang.tcl 0969ba9f13b3555e54ccdb8ec462dee2de0bf223
+F www/index.tcl 13829cd0338bc12ccc50fbcdec17d77dab6d35e0
+F www/lang.tcl d093693db5d4d7b7127d134807e4e65dea0e5dee
F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60
-F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
+F www/opcode.tcl 60222aeb57a7855b2582c374b8753cb5bb53c4ab
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
-F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
+F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
-P abff526d005b3b46904de091753cc79548739ad8
-R 4864863de07f710a3f6b561c261f5e5d
+P 82db5456c9817283d725daf4e1081d32a71466ad
+R da13c8d8c124b473a3b231a811f4208c
U drh
-Z e4c492c8b9528b70a7181a2203d31493
+Z 116b290f301c5913c5ae5b5e56236636
diff --git a/manifest.uuid b/manifest.uuid
index 34a45f0309..f843ce9e03 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-82db5456c9817283d725daf4e1081d32a71466ad
\ No newline at end of file
+d2a1aac46782c0d3852e34a3b32a6b2ccd93a256
\ No newline at end of file
diff --git a/src/os.c b/src/os.c
index 544598648f..b9d27a6464 100644
--- a/src/os.c
+++ b/src/os.c
@@ -59,7 +59,7 @@ int sqliteOsFileExists(const char *zFilename){
#endif
#if OS_WIN
HANDLE h;
- h = CreateFile(zBuf,
+ h = CreateFile(zFilename,
GENERIC_READ,
0,
NULL,
@@ -67,7 +67,7 @@ int sqliteOsFileExists(const char *zFilename){
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
- if( h!=INVALID_FILE_HANDLE ){
+ if( h!=INVALID_HANDLE_VALUE ){
CloseHandle(h);
return 1;
}
@@ -253,8 +253,11 @@ int sqliteOsTempFileName(char *zBuf){
}while( access(zBuf,0)==0 );
#endif
#if OS_WIN
+ static char zChars[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789";
int i, j;
- HANDLE h;
char zTempPath[SQLITE_TEMPNAME_SIZE];
GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
for(;;){
@@ -297,7 +300,7 @@ int sqliteOsRead(OsFile id, void *pBuf, int amt){
return got==amt ? SQLITE_OK : SQLITE_IOERR;
#endif
#if OS_WIN
- int got;
+ DWORD got;
if( !ReadFile(id, pBuf, amt, &got, 0) ){
got = 0;
}
@@ -317,7 +320,7 @@ int sqliteOsWrite(OsFile id, const void *pBuf, int amt){
return SQLITE_OK;
#endif
#if OS_WIN
- int wrote;
+ DWORD wrote;
if( !WriteFile(id, pBuf, amt, &wrote, 0) || wrote This file describes the architecture of the SQLite library.
+ This document describes the architecture of the SQLite library.
+The information here is useful to those who want to understand or
+modify the inner workings of SQLite.
+
A block diagram showing the main components of SQLite
and how they interrelate is shown at the right. The text that
follows will provide a quick overview of each of these components.
@@ -39,9 +44,8 @@ information on the C interface to SQLite is
To avoid name collisions with other software, all external
symbols in the SQLite library begin with the prefix sqlite.
-Those symbols that are intended for external use (as oppose to
-those which are for internal use only but which have to be exported
-do to limitations of the C linker's scoping mechanism) begin
+Those symbols that are intended for external use (in other words,
+those symbols which form the API for SQLite) begin
with sqlite_.Block Diagram Of SQLite
-Tokenizer
@@ -50,13 +54,14 @@ with sqlite_.
Note that in this design, the tokenizer calls the parser. People who are familiar with YACC and BISON may be used to doing things the -other way around -- having the parser call the tokenizer. This author -as done it both ways, and finds things generally work out nicer for +other way around -- having the parser call the tokenizer. The author +of SQLite +has done it both ways and finds things generally work out nicer for the tokenizer to call the parser. YACC has it backwards.
The interface to the B-tree subsystem is defined by the header file +btree.h. +
+The page cache provides the rollback and atomic commit abstraction +
The B-tree module requests information from the disk in 1024 byte +chunks. The page cache is reponsible for reading, writing, and +caching these chunks for the B-tree module. +The page cache also provides the rollback and atomic commit abstraction and takes care of reader/writer locking of the database file. The B-tree driver requests particular pages from the page cache and notifies the page cache when it wants to modify pages and commit or rollback its changes and the page cache handles all the messy details of making sure the requests are handled quickly, safely, and efficiently.
+ +The code to implement the page cache is contained in the single C +source file pager.c. The interface to the page cache subsystem +is defined by the header file pager.h. +
+ ++In order to provide portability between POSIX and Win32 operating systems, +SQLite uses an abstraction layer to interace with the operating system. +The os.c file contains about 20 routines used for opening and +closing files, deleting files, creating and deleting locks on files, +flushing the disk cache, and so forth. Each of these functions contains +two implementations separated by #ifdefs: one for POSIX and the other +for Win32. The interface to the OS abstraction layer is defined by +the os.h header file. +
} puts { diff --git a/www/c_interface.tcl b/www/c_interface.tcl index 19b4dd10db..fdbd668fb9 100644 --- a/www/c_interface.tcl +++ b/www/c_interface.tcl @@ -1,7 +1,7 @@ # # Run this Tcl script to generate the sqlite.html file. # -set rcsid {$Id: c_interface.tcl,v 1.14 2001/04/05 16:25:53 drh Exp $} +set rcsid {$Id: c_interface.tcl,v 1.15 2001/09/20 01:44:43 drh Exp $} puts { @@ -42,13 +42,21 @@ int sqlite_exec( ); #define SQLITE_OK 0 /* Successful result */ -#define SQLITE_INTERNAL 1 /* An internal logic error in SQLite */ -#define SQLITE_ERROR 2 /* SQL error or missing database */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ #define SQLITE_BUSY 5 /* One or more database files are locked */ #define SQLITE_NOMEM 6 /* A malloc() failed */ #define SQLITE_READONLY 7 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 8 /* Operation terminated by sqlite_interrupt() */ +#define SQLITE_IOERR 9 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 10 /* The database disk image is malformed */ +#define SQLITE_FULL 12 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 13 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 14 /* Database lock protocol error */ +#define SQLITE_SCHEMA 16 /* The database schema changed */ +#define SQLITE_TOOBIG 17 /* Too much data for one row of a table */Only the three core routines shown above are required to use @@ -127,39 +135,26 @@ header file that comes in the source tree.
Use the sqlite_open() function to open an existing SQLite database or to create a new SQLite database. The first argument -is the database name. The second argument is a constant 0666 to -open the database for reading and writing and 0444 to open the -database read only. The third argument is a pointer to a string -pointer. If the third argument is not NULL and an error occurs +is the database name. The second argument is intended to signal +whether the database is going to be used for reading and writing +or just for reading. But in the current implementation, the +second argument to sqlite_open is ignored. +The third argument is a pointer to a string pointer. +If the third argument is not NULL and an error occurs while trying to open the database, then an error message will be written to memory obtained from malloc() and *errmsg will be made to point to this error message. The calling function is responsible for freeing the memory when it has finished with it.
-The name of an SQLite database is normally the name of a directory -that contains a collection of GDBM files that comprise the database. -There is one GDBM file for each table and index in the -database. All GDBM files end with the ".tbl" suffix. Every SQLite -database also contains a special database table named sqlite_master -stored in its own GDBM file. This special table records the database -schema.
- -To create a new SQLite database, all you have to do is call -sqlite_open() with the first parameter set to the name of -an empty directory and the second parameter set to 0666. The -directory is created automatically if it does not already exist.
- -Beginning with SQLite version 1.0.14, SQLite supports database -backends other than GDBM. The only backends currently supported -are the default GDBM driver and an in-memory hash table database. -You may anticipate additional backends in future versions of SQLite.
- -An alternative database backend is specified by prepending the -backend name and a colon to the database name argument of the -sqlite_open() function. For the GDBM backend, you can -prepend "gdbm:" to the directory name. To select the in-memory -hash table backend, prepend "memory:" to the database name. -Future database drivers will be selected by a similar mechanism.
+The name of an SQLite database is the name of a file that will +contain the database. If the file does not exist, SQLite attempts +to create and initialize it. If the file is read-only (due to +permission bits or because it is located on read-only media like +a CD-ROM) then SQLite opens the database for reading only. The +entire SQL database is stored in a single file on the disk. But +additional temporary files may be created during the execution of +an SQL command in order to store the database rollback journal or +temporary and intermediate results of a query.
The return value of the sqlite_open() function is a pointer to an opaque sqlite structure. This pointer will @@ -172,6 +167,8 @@ for any reason.
To close an SQLite database, call the sqlite_close() function passing it the sqlite structure pointer that was obtained from a prior call to sqlite_open. +If a transaction is active when the database is closed, the transaction +is rolled back.
This return value says that the access permissions on one of the -GDBM files is such that the file cannot be opened. +
This return value says that the access permissions on the database +file are such that the file cannot be opened.
This value is returned if the callback function returns non-zero.
This return code indicates that one of the underlying GDBM files -is locked because it is currently being accessed by another thread or -process. GDBM allows mutiple readers of the same file, but only one -writer. So multiple processes can query an SQLite database at once. -But only a single process can write to an SQLite database at one time. -If an attempt is made to write to an SQLite database that another -process is currently reading, the write is not performed and -sqlite_exec() returns SQLITE_BUSY. Similarly, an attempt to read -an SQLite database that is currently being written by another process -will return SQLITE_BUSY. In both cases, the write or query attempt -can be retried after the other process finishes.
-Note that locking is done at the file level. One process can -write to table ABC (for example) while another process simultaneously -reads from a different table XYZ. But you cannot have two processes reading -and writing table ABC at the same time. +
This return code indicates that another program or thread has +the database locked. SQLite allows two or more threads to read the +database at the same time, but only one thread can have the database +open for writing at the same time. Locking in SQLite is on the +entire database.
This value is returned if a call to malloc() fails.
This return code indicates that an attempt was made to write to -a database file that was originally opened for reading only. This can -happen if the callback from a query attempts to update the table -being queried. +a database file that is opened for reading only.
This value is returned if a call to sqlite_interrupt() interrupts a database operation in progress.
This value is returned if the operating system informs SQLite +that it is unable to perform some disk I/O operation. This could mean +that there is no more space left on the disk. +
This value is returned if SQLite detects that the database it is +working on has become corrupted. Corruption might occur due to a rogue +process writing to the database file or it might happen due to an +perviously undetected logic error in of SQLite. +
This value is returned if an insertion failed because there is +no space left on the disk, or the database is too big to hold any +more information. The latter case should only occur for databases +that are larger than 2GB in size. +
This value is returned if the database file could not be opened +for some reason. +
This value is returned if some other process is messing with +file locks and has violated the file locking protocol that SQLite uses +on its rollback journal files. +
When the database first opened, SQLite reads the database schema +into memory and uses that schema to parse new SQL statements. If another +process changes the schema, the command currently being processed will +abort because the virtual machine code generated assumed the old +schema. This is the return code for such cases. Retrying the +command usually will clear the problem. +
SQLite cannot store more than about 64K of data in a single row +of a single table. If you attempt to store more than 64K in a single +row, this is the return code you get. +
The GDBM library supports database locks at the file level. -If a GDBM database file is opened for reading, then that same -file cannot be reopened for writing until all readers have closed -the file. If a GDBM file is open for writing, then the file cannot -be reopened for reading or writing until it is closed.
- -If the SQLite library attempts to open a GDBM file and finds that -the file is locked, the default action is to abort the current -operation and return SQLITE_BUSY. But this is not always the most -convenient behavior, so a mechanism exists to change it.
-The sqlite_busy_handler() procedure can be used to register a busy callback with an open SQLite database. The busy callback will -be invoked whenever SQLite tries to open a GDBM file that is locked. +be invoked whenever SQLite tries to open a locked that is locked. The callback will typically do some other useful work, or perhaps sleep, in order to give the lock a chance to clear. If the callback returns -non-zero, then SQLite tries again to open the GDBM file and the cycle +non-zero, then SQLite tries again to open the database and the cycle repeats. If the callback returns zero, then SQLite aborts the current operation and returns SQLITE_BUSY.
diff --git a/www/fileformat.tcl b/www/fileformat.tcl deleted file mode 100644 index 7b8a7439a8..0000000000 --- a/www/fileformat.tcl +++ /dev/null @@ -1,227 +0,0 @@ -# -# Run this Tcl script to generate the fileformat.html file. -# -set rcsid {$Id: fileformat.tcl,v 1.4 2000/08/04 13:49:03 drh Exp $} - -puts { - --(This page was last modified on [lrange $rcsid 3 4] GMT) -
" - -puts { -SQLite stores each SQL table and index in a separate GDBM file. -The name of the GDBM file used to store a particular table is usually -just the table name with ".tbl" appended. -Consider an example:
-} - -proc Code {body} { - puts {} -} - -Code { -$ (((rm -rf ex1))) -$ (((sqlite ex1))) -Enter ".help" for instructions -sqlite> (((create table tbl1(one varchar(10), two smallint);))) -sqlite> (((create index idx1 on tbl1(one);))) -sqlite> (((insert into tbl1 values('hello!',10);))) -sqlite> (((.exit))) -$ ls ex1 -idx1.tbl sqlite_master.tbl tbl1.tbl -$ -} - -puts { -} - regsub -all {&} [string trim $body] {\&} body - regsub -all {>} $body {\>} body - regsub -all {<} $body {\<} body - regsub -all {\(\(\(} $body {} body - regsub -all {\)\)\)} $body {} body - puts $body - puts {
The example above creates a new SQL database with a single -table named tbl1 and a single index named idx1. -Three files were created for this database. tbl1.tbl stores -all the data for the tbl1 table and idx1.tbl stores -all the information needed by the index idx1. The remaining file -sqlite_master.tbl holds the data for the special -built-in table called sqlite_master. Every SQLite database -has an sqlite_master table. This table contains the schema -for the database. You can query the sqlite_master table -using ordinary SQL commands, but you cannot write to the -sqlite_master table.
- -The GDBM file used to store an SQL table is usually -just the name of the table with .tbl appended. But there -are exceptions. First, the name of the table is converted to -all lower case letters before being used to construct the filename. -This is because SQL table names are not case sensitive but Unix filenames are. -Second, if the table name contains any characters other than -alphanumerics and underscores, the exceptional characters are encoded -as a single '+' sign. For example:
-} - -Code { -$ (((sqlite ex1))) -sqlite> (((create table 'Strange Table Name!'(a int, b char(30));))) -sqlite> .exit -$ (((ls ex1))) -idx1.tbl sqlite_master.tbl strange+table+name+.tbl tbl1.tbl -$ -} - -puts { -Each record of a GDBM file contains a key and a data. -Both key and data are arbitary bytes of any length. The information -from an SQL table is mapped into a GDBM file as follows:
- -The GDBM key for each record of an SQL table file is a -randomly chosen integer. The key size thus depends on the size -of an integer on the host computer. (Typically this means "4 bytes".) -
- -If the SQL table contains N columns, then the data entry -for each record begins with N integers. Each integer is the -offset in bytes from the beginning of the GDBM data to the -start of the data for the corresponding column. If the column -contains a NULL value, then its corresponding integer will -be zero. All column data is stored as null-terminated ASCII -text strings.
- -Consider a simple example:
-} - -Code { -$ (((rm -rf ex1))) -$ (((sqlite ex1))) -sqlite> (((create table t1(a int, b text, c text);))) -sqlite> (((insert into t1 values(10,NULL,'hello!');))) -sqlite> (((insert into t1 values(-11,'this is','a test');))) -sqlite> (((.exit))) -$ (((gdbmdump ex1/t1.tbl))) -key : 6d1a6e03 m.n. -data : 0c000000 10000000 18000000 2d313100 74686973 ............-11.this - 20697300 61207465 737400 is.a test. - -key : 6d3f90e2 m?.. -data : 0c000000 00000000 0f000000 31300068 656c6c6f ............10.hello - 2100 !. - -$ -} - -puts { -In the example above, we have created a new table named t1 -that contains two records. The gdbmdump program is used to -dump the contents of the t1 GDBM file -in a human readable format. The source code to gdbmdump -is included with the SQLite distribution. Just type "make gdbmdump" -to build it.
- -We can see in the dump of t1 that each record -is a separate GDBM entry with a 4-byte random key. The keys -shown are for a single sample run. If you try -this experiment yourself, you will probably get completely different -keys.
- -
Because the t1 table contains 3 columns, the data part of -each record begins with 3 integers. In both records of the example, -the first integer -has the value 12 since the beginning of the data for the first column -begins on the 13th byte of the record. You can see how each column's -data is stored as a null-terminated string. For the second record, -observe that the offset integer is zero for the second column. This -indicates that the second column contains NULL data.
- -Each SQL index is also represented using a single GDBM file. -There is one entry in the GDBM file for each unique SQL key in the -table that is being indexed. The GDBM key is an -arbitrary length null-terminated string which is SQL key that -is used by the index. The data is a list of integers that correspond -to GDBM keys of entries in data table that have the corresponding -SQL key. If the data record of the index is exactly 4 bytes in size, -then the data represents a single integer key. If the data is greater -than 4 bytes in size, then the first 4 bytes form an integer that -tells us how many keys are in the data. The index data record is -always sized to be a power of 2. Unused slots at the end of the -index data record are filled with zero.
- -To illustrate, we will create an index on the example table -shown above, and add a new entry to this table that has a duplicate -SQL key.
-} - -Code { -$ (((sqlite ex1))) -sqlite> (((create index i1 on t1(a);))) -sqlite> (((insert into t1 values(10,'another','record');))) -sqlite> (((.exit))) -$ (((gdbmdump ex1/t1.tbl))) -key : 223100ae "1.. -data : 0c000000 10000000 18000000 2d313100 74686973 ............-11.this - 20697300 61207465 737400 is.a test. - -key : a840e996 .@.. -data : 0c000000 00000000 0f000000 31300068 656c6c6f ............10.hello - 2100 !. - -key : c19e3119 ..1. -data : 0c000000 0f000000 17000000 31300061 6e6f7468 ............10.anoth - 65720072 65636f72 6400 er.record. -$ -} - -puts { -We added the new record to the t1 table because we wanted to -have two records with the same value on column a since that -column is used by the i1 index. You can see from the dump -above that the new t1 record is assigned another random -GDBM key.
- -Now let's look at a dump of the index file.
-} - -Code { -$ (((gdbmdump ex1/i1.tbl))) -key : 313000 10. -data : 02000000 45b4f724 6d3f90e2 00000000 ....E..$m?...... - -key : 2d313100 -11. -data : 6d1a6e03 m.n. - -$ -} - -puts { -The GDBM file for the index contains only two records because -the t1 table contains only two distinct values for -column a. You can see that the GDBM keys for each record -are just the text values for a columns of table t1. -The data for each record of the index is a list of integers -where each integer is the GDBM key for an entry in the t1 -table that has the corresponding value for the a column.
-The index entry for -11 contains only a single entry and is 4 -bytes in size. The index entry for 10 is 16 bytes in size but -contains only 2 entries. The first integer is the number of -entires. The two integer keys follow. The last 4 bytes are unused. -} - -puts { -
-Back to the SQLite Home Page
-
}
puts "This page was last modified on [lrange $rcsid 3 4] GMT
"
set vers [lindex $argv 0]
@@ -25,6 +24,10 @@ access program (sqlite) that can
be used to administer an SQLite database and which serves as
an example of how to use the SQLite library.
SQLite is not a client library used to connect to a +big database server. SQLite is the server. The SQLite +library reads and writes directly to and from the database files +on disk.
+
|
You can download a tarball containing all source +code for SQLite +} +puts "version $vers" +puts { +(including the TCL scripts that generate the +HTML files for this website) at sqlite.tar.gz.} +puts "This is a [file size sqlite.tar.gz] byte download." +set historical [lsort -dict [glob -nocomplain sqlite-*.tar.gz]] +if {$historical!=""} { + puts {The following historical versions of SQLite are also available:} + foreach x $historical { + puts "$x ([file size $x] bytes)" + } +} +puts {
} + +puts {A change history is available online. There are currently no known memory leaks or debilitating bugs in the library. Gcov -is used to verify test coverage. The test suite currently exercises -all code except for a few areas which are unreachable or which are -only reached when malloc() fails.
+is used to verify test coverage.Known bugs:
@@ -75,16 +108,10 @@ only reached when malloc() fails.A mailing list has been set up on eGroups for discussion of -SQLite design issues or for asking questions about SQLite.
-
+
![]() Click to subscribe to sqlite -} - -puts { Download- -You can download a tarball containing all source -code for SQLite + |
A mailing list has been set up on yahooGroups for discussion of +SQLite design issues or for asking questions about SQLite.
} -puts "version $vers" -puts { -(including the TCL scripts that generate the -HTML files for this website) at sqlite.tar.gz.} -puts "This is a [file size sqlite.tar.gz] byte download." -puts { +puts {To build sqlite under Unix, just unwrap the tarball, create a separate build directory, run configure from the build directory and then type "make". For example:
@@ -128,8 +149,13 @@ $ make Builds "sqlite" and "libsqlite.a" $ make test Optional: run regression tests -Instructions for building SQLite for WindowsNT are -found here. +
The Win2K version of SQLite was built using the MingW32 cross-compiler +running under Linux. You have to give the configure script hints to make +this work. Read the comments at the beginning of the file +configure.in for additional information. The source code is +general enough that it should be possible to compile SQLite using VC++, +though the author has no desire or motivation to try. +
} puts {The canonical site for GDBM is - - http://www.gnu.org/software/gdbm/gdbm.html
Someday, we would like to port SQLite to work with - the Berkeley DB library in addition to GDBM. For information - about the Berkeley DB library, see - http://www.sleepycat.com/ -
Here is a good tutorial on SQL.
Gadfly is another SQL library, similar to SQLite, except that Gadfly is written in Python.
Qgdbm is - a wrapper around - tclgdbm - that provides SQL-like access to GDBM files.
Support for transactions in SQLite is thin. Transactions -may not be nested. The GDBM backend does not support an atomic -commit or rollback, but it does support locking. (Note, however, -that the compilation instructions on this website for using GDBM under -Windows will disable locking.) The MEM backend has no transaction -support and silently ignores all requests to begin or end -transactions. A new backend is currently under -development for SQLite 2.0 that will support both atomic commits and rollback, -but that driver is not yet available.
+Beginning in version 2.0, SQLite supports transactions with +rollback and atomic commit. However, only a single level of +transaction is required. In other words, transactions +may not be nested. +
-Under GDBM, starting a transaction just locks all -tables that are either read or written during the course of the -transaction. The locks are removed when the transaction is ended. -Thus, transactions can be used to make changes to multiple tables -with the assurance that other threads or processes will not touch -the same tables at the same time. For example:
++No changes can be made to the database except within a transaction. +Any command that changes the database (basically, any SQL command +other than SELECT) will automatically starts a transaction if +when is not already in effect. Automatically stared transactions +are committed at the conclusion of the command. +
--SELECT data1, data2, ... FROM table1 WHERE ...;- -
-... Make a decision to update the table ...
-BEGIN TRANSACTION;
-SELECT data1, data2, ... FROM table1 WHERE ...;
-... Make sure no other process changed the table in between -the first SELECT and the BEGIN TRANSACTION. ...
-UPDATE table1 SET data1=... WHERE ...;
-END TRANSACTION; -
In the code above, the table1 table is locked by -the second SELECT because of the transaction. Thus we know that -no other process has modified table1 when the UPDATE -occurs. The END TRANSACTION releases the lock.
++Transactions can be started manually using the BEGIN TRANSACTION +command. Such transactions persist until a COMMIT or ROLLBACK +or until an error occurs or the database is closed. If an +error is encountered or the database is closed, the transaction +is automatically rolled back. The END TRANSACTION command is +a alias for COMMIT. +
} - Section COPY copy Syntax {sql-statement} { @@ -195,8 +185,8 @@ by the name of the new index, the keyword "ON", the name of a previously created table that is to be indexed, and a parenthesized list of names of columns in the table that are used for the index key. Each column name can be followed by one of the "ASC" or "DESC" keywords -to indicate sort order, but since GDBM does not implement ordered keys, -these keywords are ignored. +to indicate sort order, but the sort order is ignored in the current +implementation.There are no arbitrary limits on the number of indices that can be attached to a single table, nor on the number of columns in an index.
@@ -248,14 +238,11 @@ is stored as null-terminated strings. The constraints are also ignored, except that the PRIMARY KEY constraint will cause an index to be automatically created that implements the primary key and the DEFAULT constraint which specifies a default value to use when doing an INSERT. -The name of the primary -key index will be the table name -with "__primary_key" appended. The index used for a primary key -does not show up in the sqlite_master table, but a GDBM file is -created for that index. + -There are no arbitrary limits on the size of columns, on the number -of columns, or on the number of constraints in a table.
+There are no arbitrary limits on the number +of columns or on the number of constraints in a table. +The total amount of data in a single row is limited to 65535 bytes.
The exact text of each CREATE TABLE statement is stored in the sqlite_master @@ -524,8 +511,8 @@ the FROM keyword. If more than one table is specified, then the query is against the join of the various tables.
The WHERE clause can be used to limit the number of rows over -which the query operates. Note that because of limitations of -GDBM (it uses hashing not b-trees) indices will only be used to +which the query operates. In the current implementation, +indices will only be used to optimize the query if WHERE expression contains equality comparisons connected by the AND operator.
@@ -585,15 +572,21 @@ VACUUM [The VACUUM command is an SQLite extension modelled after a similar command found in PostgreSQL. If VACUUM is invoked with the name of a -table or index, then the gdbm_reorganize() function is called -on the corresponding GDBM file. If VACUUM is invoked with no arguments, -then gdbm_reorganize() is called for every GDBM file in the database.
+table or index then it is suppose to clean up the named table or index. +In the current implementation, VACUUM is a no-op. + +} -It is a good idea to run VACUUM after creating large indices, -especially indices where a single index value refers to many -entries in the data table. Reorganizing these indices will make -the underlying GDBM file much smaller and will help queries to -run much faster.
+Section PRAGMA pragma + +Syntax {sql-statement} { +PRAGMAThe PRAGMA command is used to modify the operation of the SQLite library. +Additional documentation on the PRAMGA statement is forthcoming. +
} puts { diff --git a/www/opcode.tcl b/www/opcode.tcl index abc96d762b..4e16b69e19 100644 --- a/www/opcode.tcl +++ b/www/opcode.tcl @@ -1,7 +1,7 @@ # # Run this Tcl script to generate the sqlite.html file. # -set rcsid {$Id: opcode.tcl,v 1.4 2000/07/30 20:04:43 drh Exp $} +set rcsid {$Id: opcode.tcl,v 1.5 2001/09/20 01:44:44 drh Exp $} puts { @@ -60,7 +60,11 @@ available. If you are looking for a narrative description of how the virtual machine works, you should read the tutorial and not this document. Once you have a basic idea of what the virtual machine does, you can refer back to this document for -the details on a particular opcode. +the details on a particular opcode. +Unfortunately, the virtual machine tutorial was written for +SQLite version 1.0. There are substantial changes in the virtual +machine for version 2.0 and the document has not been updated. +The source code to the virtual machine is in the vdbe.c source file. All of the opcode definitions further down in this document are @@ -84,23 +88,27 @@ Execution continues until (1) a Halt instruction is seen, or (2) the program counter becomes one greater than the address of last instruction, or (3) there is an execution error. When the virtual machine halts, all memory -that it allocated is released and all database files it may -have had open are closed.
+that it allocated is released and all database cursors it may +have had open are closed. If the execution stopped due to an +error, any pending transactions are terminated and changes made +to the database are rollback.The virtual machine also contains an operand stack of unlimited depth. Many of the opcodes use operands from the stack. See the individual opcode descriptions for details.
The virtual machine can have zero or more cursors. Each cursor -is a pointer into a single GDBM file. There can be multiple -cursors pointing at the same file. -All cursors operate independently, even cursors pointing to the same file. -The only way for the virtual machine to interact with a GDBM +is a pointer into a single table or index within the database. +There can be multiple cursors pointing at the same index or table. +All cursors operate independently, even cursors pointing to the same +indices or tables. +The only way for the virtual machine to interact with a database file is through a cursor. Instructions in the virtual machine can create a new cursor (Open), read data from a cursor -(Field), advance the cursor to the next entry in the GDBM file -(Next), and many other operations. All cursors are automatically +(Column), advance the cursor to the next entry in the table +(Next) or index (NextIdx), and many other operations. +All cursors are automatically closed when the virtual machine terminates.
The virtual machine contains an arbitrary number of fixed memory @@ -119,14 +127,12 @@ historical accident. In practice no more than one sorter
The virtual machine may contain an arbitrary number of "Lists". Each list stores a list of integers. Lists are used to hold the -GDBM keys for records of a GDBM file that needs to be modified. -(See the file format description for -more information on GDBM keys in SQLite table files.) +rowids for records of a database table that needs to be modified. The WHERE clause of an UPDATE or DELETE statement scans through -the table and writes the GDBM key of every record to be modified +the table and writes the rowid of every record to be modified into a list. Then the list is played back and the table is modified in a separate step. It is necessary to do this in two steps since -making a change to a GDBM file can alter the scan order.
+making a change to a database table can alter the scan order.The virtual machine can contain an arbitrary number of "Sets". Each set holds an arbitrary number of strings. Sets are used to @@ -174,23 +180,30 @@ Code { $ (((sqlite ex1))) sqlite> (((.explain))) sqlite> (((explain delete from tbl1 where two<20;))) -addr opcode p1 p2 p3 ----- ------------ ----- ----- ------------------------------------- -0 ListOpen 0 0 -1 Open 0 1 tbl1 -2 Next 0 9 -3 Field 0 1 -4 Integer 20 0 -5 Ge 0 2 -6 Key 0 0 -7 ListWrite 0 0 -8 Goto 0 2 -9 Noop 0 0 -10 ListRewind 0 0 -11 ListRead 0 14 -12 Delete 0 0 -13 Goto 0 11 -14 ListClose 0 0 +addr opcode p1 p2 p3 +---- ------------ ----- ----- ---------------------------------------- +0 Transaction 0 0 +1 VerifyCookie 990 0 +2 ListOpen 0 0 +3 Open 0 31 tbl1 +4 VerifyCookie 990 0 +5 Rewind 0 0 +6 Next 0 13 +7 Column 0 1 +8 Integer 20 0 +9 Ge 0 6 +10 Recno 0 0 +11 ListWrite 0 0 +12 Goto 0 6 +13 Close 0 0 +14 ListRewind 0 0 +15 Open 0 31 +16 ListRead 0 20 +17 MoveTo 0 0 +18 Delete 0 0 +19 Goto 0 16 +20 ListClose 0 0 +21 Commit 0 0 } puts { @@ -202,10 +215,18 @@ viewable.
If sqlite has been compiled without the "-DNDEBUG=1" option (that is, with the NDEBUG preprocessor macro not defined) then you can put the SQLite virtual machine in a mode where it will trace its -execution by writing messages to standard output. There are special -comments to turn tracing on and off. Use the --vdbe-trace-on-- -comment to turn tracing on and the --vdbe-trace-off-- comment -to turn tracing back off.
+execution by writing messages to standard output. The non-standard +SQL "PRAGMA" comments can be used to turn tracing on and off. To +turn tracing on, enter: + + ++ ++PRAGMA vdbe_trace=on; +
+You can turn tracing back off by entering a similar statement but +changing the value "on" to "off".
-The name of the database is usually either the name of a directory -that will contain the GDBM files that comprise the database, or it is the -name of the directory prefaced by "gdbm:". The second form -of the name is a new feature beginning in SQLite version 1.0.14 that -allows you to select alternative database backends. The default -backend is GDBM. But you can also select to store the database in -a hash table in memory by using the prefix "memory:". -Other backends may be added in the future. -
- --Every time you open an SQLite database with the memory: prefix -on the database name, you get a new in-memory database. This is true -even if you open two databases with the same name. Furthermore, -an in-memory database is automatically deleted when the database is -closed and so is not useful for persistant storage like a normal -database. But the use of an in-memory SQL database does give Tcl/Tk -a powerful new data storage mechanism that can do things that are -difficult to do with only Tcl array variables. In fact, the -hash-table backend for SQLite was created for the sole purpose of -providing better data structure support to the Tcl language. +The name of the database is just the name of a disk file in which +the database is stored.
@@ -229,19 +210,17 @@ will wait for locks to clear before giving up on a database transaction. The default timeout is 0 millisecond. (In other words, the default behavior is not to wait at all.)
-The GDBM backend allows multiple simultaneous +
The SQlite database allows multiple simultaneous readers or a single writer but not both. If any process is writing to the database no other process is allows to read or write. If any process is reading the database other processes are allowed to read but not write. -Each GDBM file is locked separately. Because each SQL table is stored as -a separate file, it is possible for different processes to write to different -database tables at the same time, just not the same table.
+The entire database shared a single lock. -When SQLite tries to open a GDBM file and finds that it is locked, it +
When SQLite tries to open a database and finds that it is locked, it can optionally delay for a short while and try to open the file again. This process repeats until the query times out and SQLite returns a failure. The timeout is adjustable. It is set to 0 by default so that -if a GDBM file is locked, the SQL statement fails immediately. But you +if the database is locked, the SQL statement fails immediately. But you can use the "timeout" method to change the timeout value to a positive number. For example:
@@ -253,14 +232,14 @@ would be 2 seconds.The "busy" method, like "timeout", only comes into play when a GDBM -file is locked. But the "busy" method gives the programmer much more +
The "busy" method, like "timeout", only comes into play when the +database is locked. But the "busy" method gives the programmer much more control over what action to take. The "busy" method specifies a callback Tcl procedure that is invoked whenever SQLite tries to open a locked -GDBM file. This callback can do whatever is desired. Presumably, the +database. This callback can do whatever is desired. Presumably, the callback will do some other useful work for a short while then return so that the lock can be tried again. The callback procedure should -return "0" if it wants SQLite to try again to open the GDBM file and +return "0" if it wants SQLite to try again to open the database and should return "1" if it wants SQLite to abandon the current operation. }