From 18df8cbede370512defa802d30606b1da04058a0 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 9 Jun 2000 01:58:35 +0000 Subject: [PATCH] :-) (CVS 87) FossilOrigin-Name: 3661b5ff93b01da7fea9f85370ecdda1402b7164 --- Makefile.in | 13 +++ manifest | 20 +++-- manifest.uuid | 2 +- src/vdbe.c | 36 +++++--- www/arch.fig | 49 +++++++++++ www/arch.png | Bin 0 -> 1687 bytes www/arch.tcl | 126 +++++++++++++++++++++++++++ www/lang.tcl | 80 +++++++++++++++--- www/opcode.tcl | 225 +++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 515 insertions(+), 36 deletions(-) create mode 100644 www/arch.fig create mode 100644 www/arch.png create mode 100644 www/arch.tcl create mode 100644 www/opcode.tcl diff --git a/Makefile.in b/Makefile.in index a986a75c07..92dfded624 100644 --- a/Makefile.in +++ b/Makefile.in @@ -188,6 +188,16 @@ fileformat.html: $(TOP)/www/fileformat.tcl lang.html: $(TOP)/www/lang.tcl tclsh $(TOP)/www/lang.tcl >lang.html +arch.html: $(TOP)/www/arch.tcl + tclsh $(TOP)/www/arch.tcl >arch.html + +arch.png: $(TOP)/www/arch.png + cp $(TOP)/www/arch.png . + +opcode.html: $(TOP)/www/opcode.tcl + tclsh $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c >opcode.html + + # Files to be published on the website. # PUBLISH = \ @@ -197,6 +207,9 @@ PUBLISH = \ changes.html \ fileformat.html \ lang.html \ + opcode.html \ + arch.html \ + arch.png \ c_interface.html website: $(PUBLISH) diff --git a/manifest b/manifest index e69719a409..e520d591bb 100644 --- a/manifest +++ b/manifest @@ -1,7 +1,7 @@ -C :-)\s(CVS\s86) -D 2000-06-08T21:53:06 +C :-)\s(CVS\s87) +D 2000-06-09T01:58:36 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4 -F Makefile.in c98978c886b94cf0d0ed414d6384501390cf0030 +F Makefile.in a0cc8da380c65002af452dfb72b3e82e1d33b04d F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958 F configure 00a5b5c82147a576fa6e82d7c1b0d55c321d6d2c x F configure.in 6ccfd5fc80517f7cfe605a7fc7e0f62d962a233c @@ -22,7 +22,7 @@ F src/tclsqlite.c 9f358618ae803bedf4fb96da5154fd45023bc1f7 F src/tokenize.c 344754f81b55da5b19ea9504dfa16a9de68cd5ba F src/update.c d8d90df714bac99c68446a0c49f3d957ca6fc3c8 F src/util.c 38e4bb5edf6fa92e677698c45785bf73c69b9e9f -F src/vdbe.c cc5598c00935ec9ec349467487182ddce9c00bce +F src/vdbe.c b7fb724aa69f4b4a488109c92cc8d64ce483821f F src/vdbe.h 8f79f57c66ce1030f6371ff067b326d627a52c6d F src/where.c c9b90e7672f4662a83ef9a27a193020d69fe034c F test/all.test 0950c135cab7e60c07bd745ccfad1476211e5bd7 @@ -53,13 +53,17 @@ F tool/memleak.awk a0a11dd84bf4582acc81c3c61271021ae49b3f15 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/c_interface.tcl 9ac800854272db5fe439e07b7435b243a5422293 F www/changes.tcl 04e66b4257589ff78a7e1de93e9dda4725fb03d6 F www/fileformat.tcl b11435fcd2cf2238a1c5e6d16fe5e83bcd14d434 F www/index.tcl b2c288000f14383501b157a57ee4506561d62f45 -F www/lang.tcl 2abf9ac0384b999c0c3f9752596abe8f8db7b2eb +F www/lang.tcl eb6a297c55d9856c94da4635eab815b09e4f96bb +F www/opcode.tcl 8be80bace48450ef4b9a34dcef4f846f7e5fb2b5 F www/sqlite.tcl 5420eab24b539928f80ea9b3088e2549d34f438d -P 8b1c151b7b2243672a0bf0ac8377e82c568bacfb -R 6dab3d7551f8822711ca5b84a3310ca7 +P 049abcb37def4200fb8f4ad7cea60a1d53ee3219 +R cbc86aaf3901beefb4f0dfae3fd3db17 U drh -Z 1919fdb42862a0c5cf9947137480de24 +Z 0d4f983c5b2e1877564119b56f0ca7bf diff --git a/manifest.uuid b/manifest.uuid index aee3426948..e72df032b4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -049abcb37def4200fb8f4ad7cea60a1d53ee3219 \ No newline at end of file +3661b5ff93b01da7fea9f85370ecdda1402b7164 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index b6b0759274..9dddb75160 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -41,7 +41,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.30 2000/06/08 16:26:25 drh Exp $ +** $Id: vdbe.c,v 1.31 2000/06/09 01:58:37 drh Exp $ */ #include "sqliteInt.h" #include @@ -946,7 +946,7 @@ int sqliteVdbeExec( break; } - /* Opcode: NULL * * * + /* Opcode: Null * * * ** ** Push a NULL value onto the stack. */ @@ -1893,7 +1893,7 @@ int sqliteVdbeExec( ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or ** off (if P2==0). In key-as-data mode, the OP_Fetch opcode pulls ** data off of the key rather than the data. This is useful for - ** outer joins and stuff... + ** processing compound selects. */ case OP_KeyAsData: { int i = pOp->p1; @@ -1910,8 +1910,12 @@ int sqliteVdbeExec( ** ** 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 if it needs - ** to persist longer than that. + ** or when P1 is closed. Make a copy of the string (using + ** "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 + ** data. */ case OP_Field: { int *pAddr; @@ -2756,8 +2760,11 @@ int sqliteVdbeExec( ** with the given key exists, create one and make it current but ** do not jump. ** - ** This opcode should not be executed after an AggNext but before - ** the next AggReset. + ** The order of aggregator opcodes is important. The order is: + ** AggReset AggFocus AggNext. In other words, you must execute + ** AggReset first, then zero or more AggFocus operations, then + ** zero or more AggNext operations. You must not execute an AggFocus + ** in between an AggNext and an AggReset. */ case OP_AggFocus: { int tos = p->tos; @@ -2852,8 +2859,8 @@ int sqliteVdbeExec( /* Opcode: AggGet * P2 * ** ** Push a new entry onto the stack which is a copy of the P2-th field - ** of the current aggregate. String are not duplicated so - ** string values will be ephemeral. + ** of the current aggregate. Strings are not duplicated so + ** string values will be ephemeral. */ case OP_AggGet: { AggElem *pFocus = AggInFocus(p->agg); @@ -2876,8 +2883,11 @@ int sqliteVdbeExec( ** aggregate is deleted. If all aggregate values have been consumed, ** jump to P2. ** - ** Do not execute an AggFocus after this opcode until after the - ** next AggReset. + ** The order of aggregator opcodes is important. The order is: + ** AggReset AggFocus AggNext. In other words, you must execute + ** AggReset first, then zero or more AggFocus operations, then + ** zero or more AggNext operations. You must not execute an AggFocus + ** in between an AggNext and an AggReset. */ case OP_AggNext: { if( p->agg.nHash ){ @@ -2905,7 +2915,7 @@ int sqliteVdbeExec( /* Opcode: SetClear P1 * * ** - ** Remove all elements from the given Set. + ** Remove all elements from the P1-th Set. */ case OP_SetClear: { int i = pOp->p1; @@ -2917,7 +2927,7 @@ int sqliteVdbeExec( /* Opcode: SetInsert P1 * P3 ** - ** If Set p1 does not exist then create it. Then insert value + ** If Set P1 does not exist then create it. Then insert value ** P3 into that set. If P3 is NULL, then insert the top of the ** stack into the set. */ diff --git a/www/arch.fig b/www/arch.fig new file mode 100644 index 0000000000..77c40f660f --- /dev/null +++ b/www/arch.fig @@ -0,0 +1,49 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 2550 2250 4875 2250 4875 3525 2550 3525 2550 2250 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 2550 4050 4875 4050 4875 5325 2550 5325 2550 4050 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 2550 5850 4875 5850 4875 7125 2550 7125 2550 5850 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 2550 7650 4875 7650 4875 8925 2550 8925 2550 7650 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 2550 450 4875 450 4875 1725 2550 1725 2550 450 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 2550 9450 4875 9450 4875 10725 2550 10725 2550 9450 +2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 75.00 135.00 + 3675 1725 3675 2250 +2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 75.00 135.00 + 3675 3525 3675 4050 +2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 75.00 135.00 + 3675 5325 3675 5850 +2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 75.00 135.00 + 3675 7125 3675 7650 +2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 75.00 135.00 + 3675 8925 3675 9450 +4 1 0 100 0 0 20 0.0000 4 195 1920 3675 8025 Virtual Machine\001 +4 1 0 100 0 0 20 0.0000 4 195 1830 3675 6225 Code Generator\001 +4 1 0 100 0 0 20 0.0000 4 195 735 3675 4350 Parser\001 +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 diff --git a/www/arch.png b/www/arch.png new file mode 100644 index 0000000000000000000000000000000000000000..a62666b83cd581f493d1dbde821bfbfd6fd06107 GIT binary patch literal 1687 zcmV;I259+-P)hlI)?K*@`J)S+1fqD5crfhwaF<2lK&~;f8|Q$Y#_- zV=&%545kwG3>`VfmR`z%Cd=jiyGz?Nz5l<=IJL?6A2c){e*F5+?_YA?wErf6y0oVH zVZ8~y90ntbrB&ph`QU(9G`{qM2$p~j5X=D$X2HF-ZC{U{q?U7X&-B24)yHs_YJ$B_ zs)Q<8c$i(|*NL11V%=XLRDfXh;rWEipL1GQa;z)9zQ@N}*IhrGh8Z*FRc5IsMm5p* z&3#4N;OcFzTe}azJmOECNAw=~6wM!_*_Aps0#>lbxW;3!DtXyEsK|x%cDhFJsH@5=wNl(T% znod}l5i)OeeUm(HVe-1z@BC>xZslti+)i~=v@$QsPML!^f#$0Q3lK9&m)kj>w6Kkz z*uZZXO$S$dcQ9kdjCuZ|Kndm&h^@qkCi(ue<4lW#w^k=2-d?W~w(_0Onry}vgZTSE zRsb+Z0@-Pp6K8j3cOIUyu-?Dr*qbe_)|EWn!Qvd-z>IS&f;luxH8H5>#>lY%+;bpV z4WU`AiG`OByzitSW^ea0UqYNC1@hOMa1$`$_iTY#KM)`aFlz$63CW*NqPWd}i-9<; z59}g4>tS~=W5$g6adCnCDDKz@vBsP^r$iwxN!`;n1mBJb;0Da8NCv?g6FGNSfvd?q zp;i&*@>4V)gg9?LP>(zloMRi9agIeWhi0iJ2G!gsIrb?tPaE$$TDO%+TBm>-x3C^C zt7W+?$`aFMeo$ty!WzisNlFAkBAwum1}7_=8Fq3a*s(QvJS-BMDlB#ol6dK}Ez@yE z@P(?l(;;SBoTK8L;Nz;RftaC z#=u=+f%Cqm%O35Wy>{NCZF^-Rje7A4dL}Dy{1FGcaAvDKSe>r0QExt(pWwgo%*4zk zhiyk+n=#nAjeRe4X_Uz+@11bqP_%u}9Bj1xuhWH?$>N%eu>gpAmGDue81=T^E0&wc z0jbQh@5Pi-#9LD4SzX|4DyC>}S2(p(nDUNHw(n0(xdV##u>7uMa{Sl_{MWWb-*d0> z9({KEy4-E5>c!LOnV{LYY5bSpSe#=Um~oCpFo$NTCI;1vb1aH4rp-xfz%gUIEvprt zQBBT+knv6*T4MEq`9WMObJhR;=N_0x9yAaPF5`mCezBJ%!KqVxI;k?bMOHR5vh!zf zsw14d+P@(~FWjXR)+akzaI%Bpt_+Wh3#^H3L8k2Btb2|VhS>{?e9&N$1!vp|lf}hb zhRH^gA7y44JCF=0Hvesp9sD96NgBMk5Tc68W5&GtoIrE7 z2G+N?lBgrO-ofyB#F1QY_U3Lx@6*|o{_uRam-!7ok_)6~$?jD?l8bX}12fLC2eBHm!k47-eTZ7#Zd*SKJ< zj$ff)Yi1#q+i4pGbH+t?pm{rjg|$Q%!&+Bz&q0j!>{;)jR(*FcW5!&M{Cfe(_e-_# z*c39yzP`Vf9P32~))lz@Ix@$eu-AQ#t-Ahi{14A0>dy_AiJ1TZ08DyRSaefwW^{L9 za%BJjc-nK&P}cO!O-xVqO-#>B&Q>tdGtx6su(Z@SFx59OR7ft$EH0^Z$gM0c$xPNu zE!ImZEy&L+(M!(H1pxF*5`gsG#9jaZ05f`2SaefqXKrD1b#i3@0C?InH#RacN-;My zPO&sJG)qZLNli0PGBZyyGDx;GH8f8F0EprUlCjq!VE_OC8G2M$bWmYuWdHzp+A}ma hsW3M%);7>K000j{0%ZyuPSyYb002ovPDHLkV1ivwCPn}N literal 0 HcmV?d00001 diff --git a/www/arch.tcl b/www/arch.tcl new file mode 100644 index 0000000000..ed818f5a7a --- /dev/null +++ b/www/arch.tcl @@ -0,0 +1,126 @@ +# +# 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 $} + +puts { + + Architecture of SQLite + + +

+The Architecture Of SQLite +

} +puts "

+(This page was last modified on [lrange $rcsid 3 4] GMT) +

" + +puts { +

Introduction

+ + + + +
Block Diagram Of SQLite
+

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 +follows will provide a quick overview of each of these components. +

+ +

Interface

+ +

The public interface to the SQLite library is implemented by +four functions found in the main.c source file. Additional +information on the C interface to SQLite is +available separately.

+ +

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 +with sqlite_.

+ +

Tokenizer

+ +

When a string containing SQL statements is to be executed, the +interface passes that string to the tokenizer. The job of the tokenizer +is to break the original string up into tokens and pass those tokens +one by one to the parser. The tokenizer is hand-coded in C. +(There is no "lex" code here.) All of the code for the tokenizer +is contained in the tokenize.c source file.

+ +

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 +the tokenizer to call the parser. YACC has it backwards.

+ +

Parser

+ +

The parser is the piece that assigns meaning to tokens based on +their context. The parser for SQLite is generated using the +Lemon 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. +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. +The source file that drives Lemon is found in parse.y.

+ +

Because +lemon is a program not normally found on development machines, the +complete source code to lemon (just one C file) is included in the +SQLite distribution in the "tool" subdirectory. Documentation on +lemon is found in the "doc" subdirectory of the distribution. +

+ +

Code Generator

+ +

After the parser assemblies 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 +files in the code generator: build.c, delete.c, +expr.c, select.c, update.c, and where.c. +In these files is where most of the serious magic happens.

+ +

Virtual Machine

+ +

The program generated by the code generator is executed by +the virtual machine. Additional information about the virtual +machine is available separately. +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 +up to three additional operands.

+ +

The virtual machine is entirely contained in a single +source file vdbe.c. The virtual machine also has +its own header file vdbe.h that defines an interface +between the virtual machine and the rest of the SQLite library.

+ +

Backend

+ +

The last layer in the design of SQLite is the backend. The +backend implements an interface between the virtual machine and +the underlying data file library -- GDBM in this case. The interface +is designed to make it easy to substitute a different database +library, such as the Berkeley DB. +The backend abstracts many of the low-level details to help +reduce the complexity of the virtual machine.

+ +

The backend is contained in the single source file dbbe.c. +The backend also has a header file dbbe.h that defines the +interface between the backend and the rest of the SQLite library.

+} + +puts { +
+


+

+Back to the SQLite Home Page +

+ +} diff --git a/www/lang.tcl b/www/lang.tcl index 4770314dba..cba2b1ebcf 100644 --- a/www/lang.tcl +++ b/www/lang.tcl @@ -1,7 +1,7 @@ # # Run this Tcl script to generate the sqlite.html file. # -set rcsid {$Id: lang.tcl,v 1.1 2000/06/08 21:53:06 drh Exp $} +set rcsid {$Id: lang.tcl,v 1.2 2000/06/09 01:58:37 drh Exp $} puts { @@ -30,9 +30,29 @@ that are part of the syntactic markup itself are shown in black roman.

by SQLite. Many low-level productions are omitted. For detailed information on the language that SQLite understands, refer to the source code.

-

CREATE TABLE

-

The basic structure of a CREATE TABLE statement is as follows:

+

SQLite implements the follow SQL commands:

+

    +} + +foreach {section} [lsort -index 0 -dictionary { + {{CREATE TABLE} createtable} + {{CREATE INDEX} createindex} + {VACUUM vacuum} + {{DROP TABLE} droptable} + {{DROP INDEX} dropindex} + {INSERT insert} + {DELETE delete} + {UPDATE update} + {SELECT select} + {COPY copy} +}] { + puts "
  • [lindex $section 0]
  • " +} +puts {

+ +

Details on the implementation of each command are provided in +the sequel.

} proc Syntax {args} { @@ -53,6 +73,20 @@ proc Syntax {args} { puts {} } +proc Section {name {label {}}} { + puts "\n
" + if {$label!=""} { + puts "" + } + puts "

$name

\n" +} + +proc Example {text} { + puts "
$text
" +} + +Section {CREATE TABLE} {createtable} + Syntax {sql-command} { CREATE TABLE ( [, ]* @@ -68,7 +102,8 @@ CREATE TABLE ( NOT NULL | PRIMARY KEY [] | UNIQUE | -CHECK ( ) +CHECK ( ) | +DEFAULT } {constraint} { PRIMARY KEY ( [, ]* ) | UNIQUE ( [, ]* ) | @@ -87,7 +122,9 @@ datatype for that column, then one or more optional column constraints. The datatype for the column is ignored. All information 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. The name of the primary +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 @@ -103,8 +140,7 @@ are read from the sqlite_master table and used to regenerate SQLite's internal representation of the table layout.

} -puts {

CREATE INDEX

-} +Section {CREATE INDEX} createindex Syntax {sql-statement} { CREATE INDEX @@ -130,10 +166,11 @@ of each CREATE INDEX statement is stored in the sqlite_master table. Everytime the database is opened, all CREATE INDEX statements are read from the sqlite_master table and used to regenerate SQLite's internal representation of the index layout.

- -

DROP TABLE

} + +Section {DROP TABLE} droptable + Syntax {sql-command} { DROP TABLE } @@ -142,10 +179,9 @@ puts {

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.

+the table are also reversibly deleted.

} -

DROP INDEX

-} +Section {DROP INDEX} dropindex Syntax {sql-command} { DROP INDEX @@ -156,10 +192,10 @@ puts { by the name of the index. The index named is completely removed from the disk. The only way to recover the index is to reenter the appropriate CREATE INDEX command.

- -

VACUUM

} +Section VACUUM vacuum + Syntax {sql-statement} { VACUUM [] } @@ -176,7 +212,23 @@ 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 INSERT insert + +Syntax {sql-statement} { +INSERT INTO [( )] VALUES ( ) | +INSERT INTO [( )] +} + +puts { +

The INSERT statement comes in two basic forms. The first form +(with the "VALUES" keyword) creates a single new row in an existing table. +If no column-list is specified then the number of values must +be the same as the number of columns in the table. If a column-list +is specified, then the number of values must match the number of +specified columns +

} puts { diff --git a/www/opcode.tcl b/www/opcode.tcl new file mode 100644 index 0000000000..5d2fafc98b --- /dev/null +++ b/www/opcode.tcl @@ -0,0 +1,225 @@ +# +# 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 $} + +puts { + + SQLite Virtual Machine Opcodes + + +

+SQLite Virtual Machine Opcodes +

} +puts "

+(This page was last modified on [lrange $rcsid 3 4] GMT) +

" + +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 Opcode($current_op:args) [lrange $line 3 end] + 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

+ } else { + append Opcode($current_op:text) \n$line + } +} +unset file + +puts { +

Introduction

+ +

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 +virtual machine.

+ +

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 +contained in comments in the source file. In fact, the opcode table +in this document +was generated by scanning the vdbe.c source file +and extracting the necessary information from comments. So the +source code comments are really the canonical source of information +about the virtual macchine. When in doubt, refer to the source code.

+ +

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.

+ +

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 files it may +have had open are closed.

+ +

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.

+ +

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. +The only way for the virtual machine to interact with a GDBM +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 +closed when the virtual machine terminates.

+ +

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.

+ +

The virtual machine contains an arbitrary number of sorters. +Each sorter is able to accumulate records, sort those records, +then play the records back in sorted order. Sorters are used +to implement the ORDER BY clause of a SELECT statement. The +fact that the virtual machine allows multiple sorters is an +historical accident. In practice no more than one sorter +(sorter number 0) ever gets used.

+ +

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. +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 +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.

+ +

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.

+ +

The virtual machine can open a single external file for reading. +This external read file is used to implement the COPY command.

+ +

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.

+ +

Viewing Programs Generated By SQLite

+ +

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.

+ +

You can use the sqlite command-line tool to see the +instructions generated by an SQL statement. The following is +an example:

} + + +proc Code {body} { + 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 {
} +} + +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 +} + +puts { +

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 sqlite +first, it will set up the output mode to make the program more easily +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.

+ +

The Opcodes

+} + +puts "

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 vdbe.c.

} + +puts { +

+} +foreach op [lsort -dictionary $OpcodeList] { + puts {" +} +puts {
Opcode NameDescription
} + puts "$op" + puts "[string trim $Opcode($op:text)]

} + +puts { +


+

+Back to the SQLite Home Page +

+ +}