aee18ef8e2
FossilOrigin-Name: 9d5abc1ddf6da37563c12d5a0401b89bb4e51c59
244 lines
10 KiB
Tcl
244 lines
10 KiB
Tcl
#
|
|
# Run this Tcl script to generate the sqlite.html file.
|
|
#
|
|
set rcsid {$Id: opcode.tcl,v 1.15 2005/03/09 12:26:51 danielk1977 Exp $}
|
|
source common.tcl
|
|
header {SQLite Virtual Machine Opcodes}
|
|
puts {
|
|
<h2>SQLite Virtual Machine Opcodes</h2>
|
|
}
|
|
|
|
set fd [open [lindex $argv 0] r]
|
|
set file [read $fd [file size [lindex $argv 0]]]
|
|
close $fd
|
|
set current_op {}
|
|
foreach line [split $file \n] {
|
|
set line [string trim $line]
|
|
if {[string index $line 1]!="*"} {
|
|
set current_op {}
|
|
continue
|
|
}
|
|
if {[regexp {^/\* Opcode: } $line]} {
|
|
set current_op [lindex $line 2]
|
|
set txt [lrange $line 3 end]
|
|
regsub -all {>} $txt {\>} txt
|
|
regsub -all {<} $txt {\<} txt
|
|
set Opcode($current_op:args) $txt
|
|
lappend OpcodeList $current_op
|
|
continue
|
|
}
|
|
if {$current_op==""} continue
|
|
if {[regexp {^\*/} $line]} {
|
|
set current_op {}
|
|
continue
|
|
}
|
|
set line [string trim [string range $line 3 end]]
|
|
if {$line==""} {
|
|
append Opcode($current_op:text) \n<p>
|
|
} else {
|
|
regsub -all {>} $line {\>} line
|
|
regsub -all {<} $line {\<} line
|
|
append Opcode($current_op:text) \n$line
|
|
}
|
|
}
|
|
unset file
|
|
|
|
puts {
|
|
<h3>Introduction</h3>
|
|
|
|
<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. This document describes the operation of that
|
|
virtual machine.</p>
|
|
|
|
<p>This document is intended as a reference, not a tutorial.
|
|
A separate <a href="vdbe.html">Virtual Machine Tutorial</a> is
|
|
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.
|
|
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.
|
|
</p>
|
|
|
|
<p>The source code to the virtual machine is in the <b>vdbe.c</b> source
|
|
file. All of the opcode definitions further down in this document are
|
|
contained in comments in the source file. In fact, the opcode table
|
|
in this document
|
|
was generated by scanning the <b>vdbe.c</b> source file
|
|
and extracting the necessary information from comments. So the
|
|
source code comments are really the canonical source of information
|
|
about the virtual machine. When in doubt, refer to the source code.</p>
|
|
|
|
<p>Each instruction in the virtual machine consists of an opcode and
|
|
up to three operands named P1, P2 and P3. P1 may be an arbitrary
|
|
integer. P2 must be a non-negative integer. P2 is always the
|
|
jump destination in any operation that might cause a jump.
|
|
P3 is a null-terminated
|
|
string or NULL. Some operators use all three operands. Some use
|
|
one or two. Some operators use none of the operands.<p>
|
|
|
|
<p>The virtual machine begins execution on instruction number 0.
|
|
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 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 rolled back.</p>
|
|
|
|
<p>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.</p>
|
|
|
|
<p>The virtual machine can have zero or more cursors. Each cursor
|
|
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
|
|
(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.</p>
|
|
|
|
<p>The virtual machine contains an arbitrary number of fixed memory
|
|
locations with addresses beginning at zero and growing upward.
|
|
Each memory location can hold an arbitrary string. The memory
|
|
cells are typically used to hold the result of a scalar SELECT
|
|
that is part of a larger expression.</p>
|
|
|
|
<p>The virtual machine contains a single sorter.
|
|
The sorter is able to accumulate records, sort those records,
|
|
then play the records back in sorted order. The sorter is used
|
|
to implement the ORDER BY clause of a SELECT statement.</p>
|
|
|
|
<p>The virtual machine contains a single "List".
|
|
The list stores a list of integers. The list is used to hold the
|
|
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 rowid of every record to be modified
|
|
into the list. Then the list is played back and the table is modified
|
|
in a separate step.</p>
|
|
|
|
<p>The virtual machine can contain an arbitrary number of "Sets".
|
|
Each set holds an arbitrary number of strings. Sets are used to
|
|
implement the IN operator with a constant right-hand side.</p>
|
|
|
|
<p>The virtual machine can open a single external file for reading.
|
|
This external read file is used to implement the COPY command.</p>
|
|
|
|
<p>Finally, the virtual machine can have a single set of aggregators.
|
|
An aggregator is a device used to implement the GROUP BY clause
|
|
of a SELECT. An aggregator has one or more slots that can hold
|
|
values being extracted by the select. The number of slots is the
|
|
same for all aggregators and is defined by the AggReset operation.
|
|
At any point in time a single aggregator is current or "has focus".
|
|
There are operations to read or write to memory slots of the aggregator
|
|
in focus. There are also operations to change the focus aggregator
|
|
and to scan through all aggregators.</p>
|
|
|
|
<h3>Viewing Programs Generated By SQLite</h3>
|
|
|
|
<p>Every SQL statement that SQLite interprets results in a program
|
|
for the virtual machine. But if you precede the SQL statement with
|
|
the keyword "EXPLAIN" the virtual machine will not execute the
|
|
program. Instead, the instructions of the program will be returned
|
|
like a query result. This feature is useful for debugging and
|
|
for learning how the virtual machine operates.</p>
|
|
|
|
<p>You can use the <b>sqlite</b> command-line tool to see the
|
|
instructions generated by an SQL statement. The following is
|
|
an example:</p>}
|
|
|
|
proc Code {body} {
|
|
puts {<blockquote><tt>}
|
|
regsub -all {&} [string trim $body] {\&} body
|
|
regsub -all {>} $body {\>} body
|
|
regsub -all {<} $body {\<} body
|
|
regsub -all {\(\(\(} $body {<b>} body
|
|
regsub -all {\)\)\)} $body {</b>} body
|
|
regsub -all { } $body {\ } body
|
|
regsub -all \n $body <br>\n body
|
|
puts $body
|
|
puts {</tt></blockquote>}
|
|
}
|
|
|
|
Code {
|
|
$ (((sqlite ex1)))
|
|
sqlite> (((.explain)))
|
|
sqlite> (((explain delete from tbl1 where two<20;)))
|
|
addr opcode p1 p2 p3
|
|
---- ------------ ----- ----- ----------------------------------------
|
|
0 Transaction 0 0
|
|
1 VerifyCookie 219 0
|
|
2 ListOpen 0 0
|
|
3 Open 0 3 tbl1
|
|
4 Rewind 0 0
|
|
5 Next 0 12
|
|
6 Column 0 1
|
|
7 Integer 20 0
|
|
8 Ge 0 5
|
|
9 Recno 0 0
|
|
10 ListWrite 0 0
|
|
11 Goto 0 5
|
|
12 Close 0 0
|
|
13 ListRewind 0 0
|
|
14 OpenWrite 0 3
|
|
15 ListRead 0 19
|
|
16 MoveTo 0 0
|
|
17 Delete 0 0
|
|
18 Goto 0 15
|
|
19 ListClose 0 0
|
|
20 Commit 0 0
|
|
}
|
|
|
|
puts {
|
|
<p>All you have to do is add the "EXPLAIN" keyword to the front of the
|
|
SQL statement. But if you use the ".explain" command to <b>sqlite</b>
|
|
first, it will set up the output mode to make the program more easily
|
|
viewable.</p>
|
|
|
|
<p>If <b>sqlite</b> 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. The non-standard
|
|
SQL "PRAGMA" comments can be used to turn tracing on and off. To
|
|
turn tracing on, enter:
|
|
</p>
|
|
|
|
<blockquote><pre>
|
|
PRAGMA vdbe_trace=on;
|
|
</pre></blockquote>
|
|
|
|
<p>
|
|
You can turn tracing back off by entering a similar statement but
|
|
changing the value "on" to "off".</p>
|
|
|
|
<h3>The Opcodes</h3>
|
|
}
|
|
|
|
puts "<p>There are currently [llength $OpcodeList] opcodes defined by
|
|
the virtual machine."
|
|
puts {All currently defined opcodes are described in the table below.
|
|
This table was generated automatically by scanning the source code
|
|
from the file <b>vdbe.c</b>.</p>}
|
|
|
|
puts {
|
|
<p><table cellspacing="1" border="1" cellpadding="10">
|
|
<tr><th>Opcode Name</th><th>Description</th></tr>}
|
|
foreach op [lsort -dictionary $OpcodeList] {
|
|
puts {<tr><td valign="top" align="center">}
|
|
puts "<a name=\"$op\">$op</a>"
|
|
puts "<td>[string trim $Opcode($op:text)]</td></tr>"
|
|
}
|
|
puts {</table></p>}
|
|
footer $rcsid
|