arch.png: $(TOP)/www/arch.png
cp $(TOP)/www/arch.png .
-opcode.html: $(TOP)/www/opcode.tcl
+opcode.html: $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c
tclsh $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c >opcode.html
-C :-)\s(CVS\s90)
-D 2000-06-09T03:52:05
+C :-)\s(CVS\s91)
+D 2000-06-09T14:14:33
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
-F Makefile.in a0cc8da380c65002af452dfb72b3e82e1d33b04d
+F Makefile.in b5693de0513e32f6e51bf0d1c62ea0d6b9a6c5d6
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
F configure 00a5b5c82147a576fa6e82d7c1b0d55c321d6d2c x
F configure.in 6ccfd5fc80517f7cfe605a7fc7e0f62d962a233c
F src/expr.c 5790665132658362f1416755cc4060215c781e90
F src/insert.c ac4edfff474589c00b2490f206317dc5822122e5
F src/main.c e3297835b8e38ca726ac73f2c2bdb7cf08103197
-F src/parse.y 03d246c261296ec85a72225ae3be999db1663e6d
+F src/parse.y 6a3085fd8e2c477e73468e6d1a278cb72254c0c9
F src/select.c 3a12d76074fa57d7c39c4436bdeb8d7e1eb6fdf4
F src/shell.c 3f4afc39a36e4824e8aa262623fd03568874799e
F src/sqlite.h 58da0a8590133777b741f9836beaef3d58f40268
F src/tokenize.c 344754f81b55da5b19ea9504dfa16a9de68cd5ba
F src/update.c d8d90df714bac99c68446a0c49f3d957ca6fc3c8
F src/util.c 38e4bb5edf6fa92e677698c45785bf73c69b9e9f
-F src/vdbe.c b7fb724aa69f4b4a488109c92cc8d64ce483821f
+F src/vdbe.c ec66bc50ac92f0cbb8582e503a8366231d3579ef
F src/vdbe.h 8f79f57c66ce1030f6371ff067b326d627a52c6d
F src/where.c c9b90e7672f4662a83ef9a27a193020d69fe034c
F test/all.test 0950c135cab7e60c07bd745ccfad1476211e5bd7
F tool/opNames.awk 2bd9071a138e4e2be13dc98fe066398a61219e1e
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/renumberOps.awk 6d067177ad5f8d711b79577b462da9b3634bd0a9
-F www/arch.fig 12da66c71585fff95bda022a9e2efda903fe2a0b
-F www/arch.png 0aa280d90d1d9249fd7ce3f08d7a227ae2963b9d
-F www/arch.tcl 282d91f509aadd0873f8aa9b357a2c0b4b175979
+F www/arch.fig 4e26e9dca3c49724fc8f554c695ddea9f2413156
+F www/arch.png c4d908b79065a72e7dcf19317f36d1324c550e87
+F www/arch.tcl 4f6a9afecc099a27bba17b4f8cc9561abc15dc40
F www/c_interface.tcl 9ac800854272db5fe439e07b7435b243a5422293
F www/changes.tcl 557a1c49e9dfca6da6d659ffc4eb202399b42b81
F www/fileformat.tcl b11435fcd2cf2238a1c5e6d16fe5e83bcd14d434
-F www/index.tcl 7d7f23b4c57008ea306aae80d2996ea7ce334f14
-F www/lang.tcl d694c3f3614aa6a6903923437d8f520a2ee97332
-F www/opcode.tcl 8be80bace48450ef4b9a34dcef4f846f7e5fb2b5
+F www/index.tcl 4116afce6a8c63d68882d2b00aa10b079e0129cd
+F www/lang.tcl 1645e9107d75709be4c6099b643db235bbe0a151
+F www/opcode.tcl 3cdc4bb2515fcfcbe853e3f0c91cd9199e82dadd
F www/sqlite.tcl 5420eab24b539928f80ea9b3088e2549d34f438d
-P 8de283ded11351962523264584c60192d1d2a4ac
-R 2e29830db7044e2492657e1175a67e0c
+P aba926bb336d7ac28d7ca73db47185801e5d2c79
+R dd39acd153ed566c1b1c836be9a51d37
U drh
-Z c126ff10a6476a9c247aae53653ed25e
+Z b881c0382203d92c75b521598ab53066
-aba926bb336d7ac28d7ca73db47185801e5d2c79
\ No newline at end of file
+d573b431ed766db2d38672334a0c81faa1dde353
\ No newline at end of file
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.19 2000/06/08 16:26:24 drh Exp $
+** @(#) $Id: parse.y,v 1.20 2000/06/09 14:14:33 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%left EQ NE ISNULL NOTNULL IS LIKE GLOB BETWEEN IN.
%left GT GE LT LE.
%left PLUS MINUS.
-%left STAR SLASH PERCENT.
+%left STAR SLASH.
%right UMINUS.
%type expr {Expr*}
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
-** $Id: vdbe.c,v 1.31 2000/06/09 01:58:37 drh Exp $
+** $Id: vdbe.c,v 1.32 2000/06/09 14:14:34 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>
/* Opcode: Open P1 P2 P3
**
- ** Open a new database table named P3. Give it an identifier P1.
+ ** Open a new cursor for the database table named P3. Give the
+ ** cursor an identifier P1.
** Open readonly if P2==0 and for reading and writing if P2!=0.
** The table is created if it does not already exist and P2!=0.
- ** If there is already another table opened on P1, then the old
- ** table is closed first. All tables are automatically closed when
+ ** If there is already another cursor opened with identifier P1,
+ ** then the old cursor is closed first.
+ ** All cursors are automatically closed when
** the VDBE finishes execution. The P1 values need not be
** contiguous but all P1 values should be small integers. It is
** an error for P1 to be negative.
**
- ** If P3 is null or an empty string, a temporary table is opened.
+ ** If P3 is null or an empty string, a temporary table created.
+ ** This table is automatically deleted when the cursor is closed.
*/
case OP_Open: {
int i = pOp->p1;
** Pop the top of the stack and use its value as a key to fetch
** a record from database table or index P1. The data is held
** in the P1 cursor until needed. The data is not pushed onto the
- ** stack or anything like that.
+ ** stack.
*/
case OP_Fetch: {
int i = pOp->p1;
** does not exist in table P1, then jump to P2. If the record
** does already exist, then fall thru. The record is not retrieved.
** The key is not popped from the stack.
+ **
+ ** This operation is similar to NotFound except that this operation
+ ** does not pop the key from the stack.
*/
/* Opcode: Found P1 P2 *
**
/* Opcode: NotFound P1 P2 *
**
** Use the top of the stack as a key. If a record with that key
- ** does exist in table P1, then jump to P2. If the record
- ** does not exist, then fall thru. The record is not retrieved.
+ ** does not exist in table P1, then jump to P2. If the record
+ ** does exist, then fall thru. The record is not retrieved.
** The key is popped from the stack.
+ **
+ ** The difference between this operation and Distinct is that
+ ** Distinct does not pop the key from the stack.
*/
case OP_Distinct:
case OP_NotFound:
** The value pushed is just a pointer to the data in the cursor.
** The value will go away the next time a record is fetched from P1,
** or when P1 is closed. Make a copy of the string (using
- ** "Concat 1 0 0" if it needs to persist longer than that.
+ ** "Concat 1 0 0") if it needs to persist longer than that.
**
** If the KeyAsData opcode has previously executed on this cursor,
** then the field might be extracted from the key rather than the
/* Opcode: PutIdx P1 * *
**
- ** The top of the stack hold an index key (proably made using the
+ ** The top of the stack hold an index key (probably made using the
** MakeKey instruction) and next on stack holds an index value for
** a table. Locate the record in the index P1 that has the key
** and insert the index value into its
/* Opcode: FileOpen * * P3
**
** Open the file named by P3 for reading using the FileRead opcode.
- ** If P3 is "stdin" then output standard input for reading.
+ ** If P3 is "stdin" then open standard input for reading.
*/
case OP_FileOpen: {
if( pOp->p3==0 ) goto bad_instruction;
/* Opcode: FileRead P1 P2 P3
**
- ** Read a single line of input the open file (the file opened using
+ ** Read a single line of input from the open file (the file opened using
** FileOpen). If we reach end-of-file, jump immediately to P2. If
** we are able to get another line, split the line apart using P3 as
- ** a delimiter. There should be exactly P1 fields. Throw an exception
- ** if the number of fields is different from P1.
+ ** a delimiter. There should be P1 fields. If the input line contains
+ ** more than P1 fields, ignore the excess. If the input line contains
+ ** fewer than P1 fields, assume the remaining fields contain an
+ ** empty string.
*/
case OP_FileRead: {
int n, eol, nField, i, c, nDelim;
4 1 0 100 0 0 20 0.0000 4 195 1140 3675 2550 Tokenizer\001
4 1 0 100 0 0 20 0.0000 4 195 1020 3675 750 Interface\001
4 1 0 100 0 0 20 0.0000 4 195 990 3675 9825 Backend\001
-4 1 0 100 0 0 14 0.0000 4 150 570 3675 10650 dbbe.c\001
-4 1 0 100 0 0 14 0.0000 4 150 570 3675 8850 vdbe.c\001
-4 1 0 100 0 0 14 0.0000 4 195 2190 3675 7050 select.c update.c where.c\001
-4 1 0 100 0 0 14 0.0000 4 195 1860 3675 6825 build.c delete.c expr.c\001
-4 1 0 100 0 0 14 0.0000 4 150 630 3675 5250 parse.y\001
-4 1 0 100 0 0 14 0.0000 4 150 870 3675 3450 tokenize.c\001
4 1 0 100 0 0 14 0.0000 4 150 570 3675 1575 main.c\001
+4 1 0 100 0 0 14 0.0000 4 195 1860 3675 6525 build.c delete.c expr.c\001
+4 1 0 100 0 0 14 0.0000 4 195 2115 3675 6750 insert.c select.c update.c\001
+4 1 0 100 0 0 14 0.0000 4 150 705 3675 6975 where.c\001
+4 1 0 100 0 0 14 0.0000 4 150 630 3675 5175 parse.y\001
+4 1 0 100 0 0 14 0.0000 4 150 870 3675 3375 tokenize.c\001
+4 1 0 100 0 0 14 0.0000 4 150 570 3675 8775 vdbe.c\001
+4 1 0 100 0 0 14 0.0000 4 150 570 3675 10500 dbbe.c\001
#
# Run this Tcl script to generate the sqlite.html file.
#
-set rcsid {$Id: arch.tcl,v 1.1 2000/06/09 01:58:51 drh Exp $}
+set rcsid {$Id: arch.tcl,v 1.2 2000/06/09 14:14:34 drh Exp $}
puts {<html>
<head>
</table>
<p>This file describes the architecture of the SQLite library.
A block diagram showing the main components of SQLite
-and how that interrelate is shown at the right. The text that
+and how they interrelate is shown at the right. The text that
follows will provide a quick overview of each of these components.
</p>
their context. The parser for SQLite is generated using the
<a href="http://www.hwaci.com/sw/lemon/">Lemon</a> LALR(1) parser
generator. Lemon does the same job as YACC/BISON, but is uses
-a different input syntax which is less error-prone than the
-clumsy YACC/BISON syntax.
+a different input syntax which is less error-prone.
Lemon also generates a parser which is reentrant and thread-safe.
And lemon defines the concept of a non-terminal destructor so
that it does not leak memory when syntax errors are encountered.
<h2>Code Generator</h2>
-<p>After the parser assemblies tokens into complete SQL statements,
+<p>After the parser assembles tokens into complete SQL statements,
it calls the code generator to produce virtual machine code that
-will do the work that the SQL statements request. There are six
+will do the work that the SQL statements request. There are seven
files in the code generator: <b>build.c</b>, <b>delete.c</b>,
-<b>expr.c</b>, <b>select.c</b>, <b>update.c</b>, and <b>where.c</b>.
-In these files is where most of the serious magic happens.</p>
+<b>expr.c</b>, <b>insert.c</b> <b>select.c</b>, <b>update.c</b>,
+and <b>where.c</b>.
+In these files is where most of the serious magic happens.
+<b>expr.c</b> handles code generation for expressions.
+<b>where.c</b> handles code generation for WHERE clauses on
+SELECT, UPDATE and DELETE statements. The files
+<b>delete.c</b>, <b>insert.c</b>, <b>select.c</b>, and
+<b>update.c</b> handle the code generation for SQL statements
+with the same names. (Each of these files calls routines
+in <b>expr.c</b> and <b>where.c</b> as necessary.) All other
+SQL statements are coded out of <b>build.c</b>.</p>
<h2>Virtual Machine</h2>
machine is <a href="opcode.html">available separately</a>.
To summarize, the virtual machine implements an abstract computing
engine specifically designed to manipulate database files. The
-machine as a stack. Each instruction contains an opcode and
+machine has a stack which is used for intermediate storage.
+Each instruction contains an opcode and
up to three additional operands.</p>
<p>The virtual machine is entirely contained in a single
#
# Run this TCL script to generate HTML for the index.html file.
#
-set rcsid {$Id: index.tcl,v 1.17 2000/06/09 03:51:27 drh Exp $}
+set rcsid {$Id: index.tcl,v 1.18 2000/06/09 14:14:34 drh Exp $}
puts {<html>
<head><title>SQLite: An SQL Database Engine Built Atop GDBM</title></head>
<p><ul>
<li>Information on the <a href="sqlite.html">sqlite</a>
command-line utility.</li>
+<li>The <a href="lang.html">SQL Language</a> subset understood by SQLite.</li>
<li>The <a href="c_interface.html">C/C++ Interface</a>.</li>
<li>The <a href="fileformat.html">file format</a> used by SQLite databases.</li>
<li>The <a href="arch.html">Architecture of the SQLite Library</a> describes
- how the library is put together. <b>(preliminary)</b></li>
+ how the library is put together.</li>
<li>A description of the <a href="opcode.html">virtual machine</a> that
- SQLite uses to access the database. <b>(preliminary)</b></li>
-<li>The <a href="lang.html">SQL Language</a> subset understood by SQLite.
- <b>(under development)</b></li>
+ SQLite uses to access the database.</li>
</ul>
</p>
#
# Run this Tcl script to generate the sqlite.html file.
#
-set rcsid {$Id: lang.tcl,v 1.3 2000/06/09 03:47:19 drh Exp $}
+set rcsid {$Id: lang.tcl,v 1.4 2000/06/09 14:14:34 drh Exp $}
puts {<html>
<head>
{SELECT select}
{COPY copy}
{EXPLAIN explain}
- {expressions expr}
+ {expression expr}
}] {
puts "<li><a href=\"#[lindex $section 1]\">[lindex $section 0]</a></li>"
}
}
puts {</table>}
}
+proc Operator {name} {
+ return "<font color=\"#2c2cf0\"><big>$name</big></font>"
+}
+proc Nonterminal {name} {
+ return "<i><font color=\"#ff3434\">$name</font></i>"
+}
+proc Keyword {name} {
+ return "<font color=\"#2c2cf0\">$name</font>"
+}
+
proc Section {name {label {}}} {
puts "\n<hr />"
Section COPY copy
Syntax {sql-statement} {
-COPY <table-name> FROM <string>
+COPY <table-name> FROM <filename>
}
+puts {
+<p>The COPY command is an extension used to load large amounts of
+data into a table. It is modeled after a similar command found
+in PostgreSQL. In fact, the SQLite COPY command is specifically
+designed to be able to read the output of the PostgreSQL dump
+utility <b>pg_dump</b> so that data can be easily transferred from
+PostgreSQL into SQLite.<p>
+
+<p>The table-name is the name of an existing table which is to
+be filled with data. The filename is a string or identifier that
+names a file from which data will be read. The filename can be
+the <b>STDIN</b> to read data from standard input.<p>
+
+<p>Each line of the input file is converted into a single record
+in the table. Columns are separated by tabs. If a tab occurs as
+data within a column, then that tab is preceded by a baskslash "\"
+character. A baskslash in the data appears as two backslashes in
+a row.</p>
+
+<p>When the input data source is STDIN, the input can be terminated
+by a line that contains only a baskslash and a dot:}
+puts "\"[Operator \\.]\".</p>"
+
Section {CREATE INDEX} createindex
Syntax {sql-statement} {
}
puts {
-<p></p>
+<p>The DELETE command is used to remove records from a table.
+The command consists of the "DELETE FROM" keywords followed by
+the name of the table from which records are to be removed.
+</p>
+
+<p>Without a WHERE clause, all rows of the table are removed.
+If a WHERE clause is supplied, then only those rows that match
+the expression are removed.</p>
}
+
Section {DROP INDEX} dropindex
Syntax {sql-command} {
<p>The DROP TABLE statement consists of the keywords "DROP TABLE" followed
by the name of the table. The table named is completely removed from
the disk. The table can not be recovered. All indices associated with
-the table are also reversibly deleted.</p>}
+the table are also deleted.</p>}
Section EXPLAIN explain
EXPLAIN <sql-statement>
}
+puts {
+<p>The EXPLAIN command modifier is a non-standard extension. The
+idea comes from a similar command found in PostgreSQL, but the operation
+is completely different.</p>
+
+<p>If the EXPLAIN keyword appears before any other SQLite SQL command
+then instead of actually executing the command, the SQLite library will
+report back the sequence of virtual machine instructions it would have
+used to execute the command had the EXPLAIN keyword not been present.
+For additional information about virtual machine instructions see
+the <a href="arch.html">architecture description</a> or the documentation
+on <a href="opcode.html">available opcodes</a> for the virtual machine.</p>
+}
+
Section expression expr
Syntax {expression} {
<function-name> ( <expr-list> | STAR ) |
<expression> ISNULL |
<expression> NOTNULL |
-<expression> BETWEEN <expression> AND <expression> |
-<expression> IN ( <value-list> ) |
-<expression> IN ( <select> ) |
+<expression> [NOT] BETWEEN <expression> AND <expression> |
+<expression> [NOT] IN ( <value-list> ) |
+<expression> [NOT] IN ( <select> ) |
( <select> )
} {like-op} {
LIKE | GLOB | NOT LIKE | NOT GLOB
}
+puts {
+<p>This section is different from the others. Every other section of
+this document talks about a particular SQL command. This section does
+not talk about a standalone command but about "expressions" which are
+subcomponent of most other commands.</p>
+
+<p>SQLite understands the following binary operators, in order from
+highest to lowest precedence:</p>
+
+<blockquote><pre>
+<font color="#2c2cf0"><big>* /
++ -
+< <= > >=
+= == != <> </big>IN
+AND
+OR</font>
+</pre></blockquote>
+
+<p>Any SQLite value can be used as part of an expression.
+For arithmetic operations, integers are treated as integers.
+Strings are first converted to real numbers using <b>atof()</b>.
+For comparison operators, numbers compare as numbers and strings
+compare as strings. For string comparisons, case is significant
+but is only used to break a tie.
+Note that there are two variations of the equals and not equals
+operators. Equals can be either}
+puts "[Operator =] or [Operator ==].
+The non-equals operator can be either
+[Operator !=] or [Operator {<>}].</p>"
+puts {
+
+<p>The LIKE operator does a wildcard comparision. The operand
+to the right contains the wildcards.}
+puts "A percent symbol [Operator %] in the right operand
+matches any sequence of zero or more characters on the left.
+An underscore [Operator _] on the right
+matches any single character on the left. The LIKE operator is
+not case sensitive and will match upper case characters on one
+side against lower case characters on the other.</p>"
+puts {
+
+<p>The GLOB operator is similar to LIKE but uses the Unix
+file globbing syntax for its wildcards. Also, GLOB is case
+sensitive, unlike LIKE. Both GLOB and LIKE may be preceded by
+the NOT keyword to invert the sense of the test.</p>
+
+<p>SELECT statements can appear in expressions as either the
+right-hand operand of the IN operator or as a scalar quantity.
+In both cases, the SELECT should have only a single column in its
+result. Compound SELECTs (connected with keywords like UNION or
+EXCEPT) are allowed. Any ORDER BY clause on the select is ignored.
+A SELECT in an expression is evaluated once before any other processing
+is performed, so none of the expressions within the select itself can
+refer to quantities in the containing expression.</p>
+
+<p>When a SELECT is the right operand of the IN operator, the IN
+operator returns TRUE if the result of the left operand is any of
+the values generated by the select. The IN operator may be preceded
+by the NOT keyword to invert the sense of the test.</p>
+
+<p>When a SELECT appears within an expression but is not the right
+operand of an IN operator, then the first row of the result of the
+SELECT becomes the value used in the expression. If the SELECT yields
+more than one result row, all rows after the first are ignored. If
+the SELECT yeilds no rows, then the value of the SELECT is NULL.</p>
+}
+
Section INSERT insert
Syntax {sql-statement} {
[<compound-op> <select>]*
[ORDER BY <sort-expr-list>]
} {result} {
-STAR | <expresssion> [, <expression>]*
+STAR | <result-column> [, <result-column>]*
+} {result-column} {
+<expression> [ [AS] <string> ]
} {table-list} {
<table-name> [, <table-name>]*
} {sort-expr-list} {
UNION | UNION ALL | INTERSECT | EXCEPT
}
+puts {
+<p>The SELECT statement is used to query the database. The
+result of a SELECT is zero or more rows of data where each row
+has a fixed number of columns. The number of columns in the
+result is specified by the expression list in between the
+SELECT and FROM keywords. Any arbitrary expression can be used
+as a result. If the result specification is just}
+puts "[Operator *] then all columns of all tables are used as the result."
+puts {</p>
+
+<p>The query is executed again one or more tables specified after
+the FROM keyword. If more than one table is specified, then the
+query is against the join of the various tables.</p>
+
+<p>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
+optimize the query if WHERE expression contains equality comparisons
+connected by the AND operator.</p>
+
+<p>The GROUP BY clauses causes one or more rows of the result to
+be combined into a single row of output. This is especially useful
+when the result contains aggregate functions. The expressions in
+the GROUP BY clause do <em>not</em> have to be expressions that
+appear in the result. The HAVING clause is similar to WHERE except
+that HAVING applies after grouping has occurred. The HAVING expression
+may refer to values, even aggregate functions, that are not in the result.</p>
+
+<p>The ORDER BY clause causes the output rows to be sorted.
+The argument to ORDER BY is a list of expressions that are used as the
+key for the sort. The expressions do not have to be part of the
+result for a simple SELECT, but in a compound SELECT each sort
+expression must exactly match one of the result columns. Each
+sort expression may be optionally followed by ASC or DESC to specify
+the sort order.</p>
+
+<p>A compound SELECT is formed from two or more simple SELECTs connected
+by one of the operators UNION, UNION ALL, INTERSECT, or EXCEPT. In
+a compound SELECT, all the constituent SELECTs must specify the
+same number of result columns. There may be only a single ORDER BY
+clause at the end of the compound SELECT. The UNION and UNION ALL
+operators combine the results of the SELECTs to the right and left into
+a single big table. The difference is that in UNION all result rows
+are distinct where in UNION ALL there may be duplicates.
+The INTERSECT operator takes the intersection of the results of the
+left and right SELECTs. EXCEPT takes the result of left SELECT after
+removing the results of the right SELECT. When three are more SELECTs
+are connected into a compound, they group from left to right.</p>
+}
+
Section UPDATE update
Syntax {sql-statement} {
}
puts {
-<p>
+<p>The UPDATE statement is used to change the value of columns in
+selected rows of a table. Each assignment in an UPDATE specifies
+a column name to the left of the equals sign and an arbitrary expression
+to the right. The expressions may use the values of other columns.
+All expressions are evaluated before any assignments are made.
+A WHERE clause can be used to restrict which rows are updated.
}
Section VACUUM vacuum
#
# Run this Tcl script to generate the sqlite.html file.
#
-set rcsid {$Id: opcode.tcl,v 1.1 2000/06/09 01:58:37 drh Exp $}
+set rcsid {$Id: opcode.tcl,v 1.2 2000/06/09 14:14:34 drh Exp $}
puts {<html>
<head>
<p>In order to execute an SQL statement, the SQLite library first parses
the SQL, analyzes the statement, then generates a short program to execute
the statement. The program is generated for a "virtual machine" implemented
-by the SQLite library. The document describes the operation of that
+by the SQLite library. This document describes the operation of that
virtual machine.</p>
<p>The source code to the virtual machine is in the <b>vdbe.c</b> source
have had open are closed.</p>
<p>The virtual machine also contains an operand stack of unlimited
-depth. Many of the opcodes use operands from the stack. The details
-are described in the descriptions of each opcode.</p>
+depth. Many of the opcodes use operands from the stack. See the
+individual opcode descriptions for details.</p>
<p>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 independenly.
+All cursors operate independently, even cursors pointing to the same file.
The only way for the virtual machine to interact with a GDBM
file is through a cursor.
Instructions in the virtual
<p>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 <a href="fileformat.html">file format</a> description for
+more information on GDBM keys in SQLite table files.)
The WHERE clause of an UPDATE or DELETE statement scans through
the table and writes the GDBM key of every record to be modified
into a list. Then the list is played back and the table is modified