1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Remove cruft: restrict the number of sorters and lists in the VDBE to one

since no more than one was ever used anyway.  This eliminates several
op-codes and simplifies the implementation of several others. (CVS 297)

FossilOrigin-Name: e1370276c2a0d045b29c981ddcb59f737e19a91c
This commit is contained in:
drh
2001-11-01 14:41:34 +00:00
parent 18b81e5a93
commit a8b38d286e
12 changed files with 230 additions and 349 deletions

10
README
View File

@@ -21,3 +21,13 @@ script does not work out for you, there is a generic makefile named
"Makefile.template" in the top directory of the source tree that you "Makefile.template" in the top directory of the source tree that you
can copy and edit to suite your needs. Comments on the generic makefile can copy and edit to suite your needs. Comments on the generic makefile
show what changes are needed. show what changes are needed.
The windows binaries on the website are created using MinGW32 configured
as a cross-compiler running under Linux. For details, see the ./publish.sh
script at the top-level of the source tree.
Contacts:
http://www.hwaci.com/sw/sqlite/
http://groups.yahoo.com/group/sqlite/
drh@hwaci.com

View File

@@ -1,8 +1,8 @@
C Comment\schanges\sonly.\s(CVS\s296) C Remove\scruft:\srestrict\sthe\snumber\sof\ssorters\sand\slists\sin\sthe\sVDBE\sto\sone\nsince\sno\smore\sthan\sone\swas\sever\sused\sanyway.\s\sThis\seliminates\sseveral\nop-codes\sand\ssimplifies\sthe\simplementation\sof\sseveral\sothers.\s(CVS\s297)
D 2001-11-01T13:52:53 D 2001-11-01T14:41:34
F Makefile.in 6801df952cb1df64aa32e4de85fed24511d28efd F Makefile.in 6801df952cb1df64aa32e4de85fed24511d28efd
F Makefile.template 1fdb891f14083ee0b63cf7282f91529634438e7a F Makefile.template 1fdb891f14083ee0b63cf7282f91529634438e7a
F README 93d2977cc5c6595c448de16bdefc312b9d401533 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
F VERSION 46489bc13fe8b494327fecb3c9a05f4db2e284b3 F VERSION 46489bc13fe8b494327fecb3c9a05f4db2e284b3
F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588 F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588
@@ -17,12 +17,12 @@ F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F libtool c56e618713c9510a103bda6b95f3ea3900dcacd6 F libtool c56e618713c9510a103bda6b95f3ea3900dcacd6
F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1 F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1
F publish.sh badcd69b8e3a8bc69b162c4c9d7c209b2a0b119e F publish.sh 33cbe6798969f637698044023c139080e5d772a6
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
F src/btree.c f5b3bf49c98a90754097e8f0a946931d9cc857ef F src/btree.c f5b3bf49c98a90754097e8f0a946931d9cc857ef
F src/btree.h 57d653ef5137b91f2a068aaf71a2905468dd2cb7 F src/btree.h 57d653ef5137b91f2a068aaf71a2905468dd2cb7
F src/build.c 8857c16751a5e9c5ee845e1b3cf2da78935c8cb3 F src/build.c 8857c16751a5e9c5ee845e1b3cf2da78935c8cb3
F src/delete.c 6fe2191c49c4a31336e2fac11b3ad665ddcd4246 F src/delete.c a4c13c444544f315703d5fbed6419c8786f66581
F src/expr.c 2dd0252ced345c1e64db015b94dc6b5d7a57eef3 F src/expr.c 2dd0252ced345c1e64db015b94dc6b5d7a57eef3
F src/hash.c d0110e6da70a5962e21575fccf8206f7d9d75e00 F src/hash.c d0110e6da70a5962e21575fccf8206f7d9d75e00
F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
@@ -36,7 +36,7 @@ F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca
F src/parse.y 148e4cd134d3cbd816dcb0df50e49e498faa6ba4 F src/parse.y 148e4cd134d3cbd816dcb0df50e49e498faa6ba4
F src/printf.c 167fbfb192b4dce48154398f22dbc614e9f5d088 F src/printf.c 167fbfb192b4dce48154398f22dbc614e9f5d088
F src/random.c 2a9cc2c9716d14815fd4c2accf89d87a1143e46b F src/random.c 2a9cc2c9716d14815fd4c2accf89d87a1143e46b
F src/select.c d14511afacf788bf4a0c517011c2c53038539388 F src/select.c c34b02eafaa69fde6b4428df7861c3417b3079f9
F src/shell.c 71597951753b56a97fea1c7a30908f31e635c00c F src/shell.c 71597951753b56a97fea1c7a30908f31e635c00c
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in f2c40c869ff40ad3e60d8a3b1f72777fa28b32fc F src/sqlite.h.in f2c40c869ff40ad3e60d8a3b1f72777fa28b32fc
@@ -47,10 +47,10 @@ F src/test1.c e4b31f62ea71963cbae44338acf477a04fc8fc49
F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321 F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
F src/test3.c 4a0d7b882fdae731dbb759f512ad867122452f96 F src/test3.c 4a0d7b882fdae731dbb759f512ad867122452f96
F src/tokenize.c 8f4c2b5e7fb471ba194979fb4dd5f947402fd792 F src/tokenize.c 8f4c2b5e7fb471ba194979fb4dd5f947402fd792
F src/update.c c916182c6bfbc8a6f20c24920c4560fece6c9569 F src/update.c 4eeb154a2da8a934d180e2d9e4211ac0a7a4ce8b
F src/util.c aa4d2de60cb2445239b71c79c3a8c0b7c0d3336a F src/util.c aa4d2de60cb2445239b71c79c3a8c0b7c0d3336a
F src/vdbe.c 4b0df66646648a7f60037926015ec2c181536f53 F src/vdbe.c 9e4fd512dd3e66d37f5b53ae88138fda4f9aa227
F src/vdbe.h f8407fd6b644bc001b1e7c65460c9962f6a15f6b F src/vdbe.h 4a587ec56943d34698edf507ad5a746e87cb8cf4
F src/where.c 22fe910c7c8e2736eb37e9861343e90c0b513c86 F src/where.c 22fe910c7c8e2736eb37e9861343e90c0b513c86
F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe
F test/bigrow.test a35f2de9948b24e427fb292c35947795efe182d0 F test/bigrow.test a35f2de9948b24e427fb292c35947795efe182d0
@@ -102,19 +102,19 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
F www/arch.tcl 03b521d252575f93b9c52f7c8b0007011512fcfb F www/arch.tcl 03b521d252575f93b9c52f7c8b0007011512fcfb
F www/c_interface.tcl d446234c1d3ed747fcefd30e972a19f2b2fc0e05 F www/c_interface.tcl d446234c1d3ed747fcefd30e972a19f2b2fc0e05
F www/changes.tcl 995d934eb54762d766923241a5a2e6023a0f3c6e F www/changes.tcl 37ca708eb350dc41fcf3ea0ae8ecc705c0c218bf
F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
F www/download.tcl 3e51c9ff1326b0a182846134987301310dff7d60 F www/download.tcl 3e51c9ff1326b0a182846134987301310dff7d60
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
F www/index.tcl 7c7df8d73c751897b643018fd21317269f10e023 F www/index.tcl b9d166d09fa4237d31d78be49f2b8b205e6e7678
F www/lang.tcl 1899ec4fb77cd69de335ebd998253de869f34d8e F www/lang.tcl 1899ec4fb77cd69de335ebd998253de869f34d8e
F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60 F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60
F www/opcode.tcl 4365ad9798872491dbd7d3071510ebe461785ac3 F www/opcode.tcl 7989ed328316454c7030dcdb60f09ae1e017286d
F www/speed.tcl 212a91d555384e01873160d6a189f1490c791bc2 F www/speed.tcl 212a91d555384e01873160d6a189f1490c791bc2
F www/sqlite.tcl 6a21242a272e9c0939a04419a51c3d50cae33e3e F www/sqlite.tcl 6a21242a272e9c0939a04419a51c3d50cae33e3e
F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa
F www/vdbe.tcl bb7d620995f0a987293e9d4fb6185a3b077e9b44 F www/vdbe.tcl bb7d620995f0a987293e9d4fb6185a3b077e9b44
P f65df59e554c281ad1efa830f13f87488eb16845 P b2cb118fb7c6713684d32a48a7ba8ffffe596687
R 50f675a2d3f94fcb2f093eaf90b1247b R 11be61d659c8d3b7f97b8d20e188eb7e
U drh U drh
Z 77ddce4c95e7ba412288de1a3a02ea29 Z 1756e792427d370fb3a08a33a148f36d

View File

@@ -1 +1 @@
b2cb118fb7c6713684d32a48a7ba8ffffe596687 e1370276c2a0d045b29c981ddcb59f737e19a91c

View File

@@ -90,7 +90,8 @@ zip sqlite.zip sqlite.exe
ORIGIN=`pwd` ORIGIN=`pwd`
cd $srcdir cd $srcdir
cd .. cd ..
tar czf $ORIGIN/sqlite.tar.gz sqlite EXCLUDE=`find sqlite -print | grep CVS | sed 's,sqlite/, --exclude sqlite/,'`
tar czf $ORIGIN/sqlite.tar.gz $EXCLUDE sqlite
cd $ORIGIN cd $ORIGIN
vers=`cat $srcdir/VERSION` vers=`cat $srcdir/VERSION`
rm -f sqlite-$vers.tar.gz rm -f sqlite-$vers.tar.gz

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements. ** to handle DELETE FROM statements.
** **
** $Id: delete.c,v 1.18 2001/10/15 00:44:36 drh Exp $ ** $Id: delete.c,v 1.19 2001/11/01 14:41:34 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -125,7 +125,6 @@ void sqliteDeleteFrom(
else{ else{
/* Begin the database scan /* Begin the database scan
*/ */
sqliteVdbeAddOp(v, OP_ListOpen, 0, 0);
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1); pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
if( pWInfo==0 ) goto delete_from_cleanup; if( pWInfo==0 ) goto delete_from_cleanup;
@@ -168,7 +167,7 @@ void sqliteDeleteFrom(
sqliteVdbeAddOp(v, OP_Delete, base, 0); sqliteVdbeAddOp(v, OP_Delete, base, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, addr); sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end); sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_ListClose, 0, 0); sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
} }
if( (db->flags & SQLITE_InTrans)==0 ){ if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0); sqliteVdbeAddOp(v, OP_Commit, 0, 0);

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite. ** to handle SELECT statements in SQLite.
** **
** $Id: select.c,v 1.44 2001/10/22 02:58:10 drh Exp $ ** $Id: select.c,v 1.45 2001/11/01 14:41:34 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -222,7 +222,7 @@ static void generateSortTail(Vdbe *v, int nColumn){
sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0); sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, addr); sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end); sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_SortClose, 0, 0); sqliteVdbeAddOp(v, OP_SortReset, 0, 0);
} }
/* /*
@@ -551,9 +551,6 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
int iCont, iBreak; int iCont, iBreak;
assert( p->pEList ); assert( p->pEList );
generateColumnNames(pParse, 0, p->pEList); generateColumnNames(pParse, 0, p->pEList);
if( p->pOrderBy ){
sqliteVdbeAddOp(v, OP_SortOpen, 0, 0);
}
sqliteVdbeAddOp(v, OP_Rewind, unionTab, 0); sqliteVdbeAddOp(v, OP_Rewind, unionTab, 0);
iBreak = sqliteVdbeMakeLabel(v); iBreak = sqliteVdbeMakeLabel(v);
iCont = sqliteVdbeAddOp(v, OP_Next, unionTab, iBreak); iCont = sqliteVdbeAddOp(v, OP_Next, unionTab, iBreak);
@@ -605,9 +602,6 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
*/ */
assert( p->pEList ); assert( p->pEList );
generateColumnNames(pParse, 0, p->pEList); generateColumnNames(pParse, 0, p->pEList);
if( p->pOrderBy ){
sqliteVdbeAddOp(v, OP_SortOpen, 0, 0);
}
sqliteVdbeAddOp(v, OP_Rewind, tab1, 0); sqliteVdbeAddOp(v, OP_Rewind, tab1, 0);
iBreak = sqliteVdbeMakeLabel(v); iBreak = sqliteVdbeMakeLabel(v);
iCont = sqliteVdbeAddOp(v, OP_Next, tab1, iBreak); iCont = sqliteVdbeAddOp(v, OP_Next, tab1, iBreak);
@@ -859,9 +853,6 @@ int sqliteSelect(
*/ */
v = sqliteGetVdbe(pParse); v = sqliteGetVdbe(pParse);
if( v==0 ) return 1; if( v==0 ) return 1;
if( pOrderBy ){
sqliteVdbeAddOp(v, OP_SortOpen, 0, 0);
}
/* Identify column names if we will be using in the callback. This /* Identify column names if we will be using in the callback. This
** step is skipped if the output is going to a table or a memory cell. ** step is skipped if the output is going to a table or a memory cell.

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle UPDATE statements. ** to handle UPDATE statements.
** **
** $Id: update.c,v 1.19 2001/10/15 00:44:36 drh Exp $ ** $Id: update.c,v 1.20 2001/11/01 14:41:34 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -143,7 +143,6 @@ void sqliteUpdate(
/* Begin the database scan /* Begin the database scan
*/ */
sqliteVdbeAddOp(v, OP_ListOpen, 0, 0);
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1); pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
if( pWInfo==0 ) goto update_cleanup; if( pWInfo==0 ) goto update_cleanup;
@@ -233,7 +232,7 @@ void sqliteUpdate(
*/ */
sqliteVdbeAddOp(v, OP_Goto, 0, addr); sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end); sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_ListClose, 0, 0); sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
if( (db->flags & SQLITE_InTrans)==0 ){ if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0); sqliteVdbeAddOp(v, OP_Commit, 0, 0);
} }

View File

@@ -30,7 +30,7 @@
** But other routines are also provided to help in building up ** But other routines are also provided to help in building up
** a program instruction by instruction. ** a program instruction by instruction.
** **
** $Id: vdbe.c,v 1.90 2001/11/01 13:52:54 drh Exp $ ** $Id: vdbe.c,v 1.91 2001/11/01 14:41:34 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -187,10 +187,8 @@ struct Vdbe {
char **azColName; /* Becomes the 4th parameter to callbacks */ char **azColName; /* Becomes the 4th parameter to callbacks */
int nCursor; /* Number of slots in aCsr[] */ int nCursor; /* Number of slots in aCsr[] */
Cursor *aCsr; /* On element of this array for each open cursor */ Cursor *aCsr; /* On element of this array for each open cursor */
int nList; /* Number of slots in apList[] */ Keylist *pList; /* A list of ROWIDs */
Keylist **apList; /* For each Keylist */ Sorter *pSort; /* A linked list of objects to be sorted */
int nSort; /* Number of slots in apSort[] */
Sorter **apSort; /* An open sorter list */
FILE *pFile; /* At most one open file handler */ FILE *pFile; /* At most one open file handler */
int nField; /* Number of file fields */ int nField; /* Number of file fields */
char **azField; /* Data for each file field */ char **azField; /* Data for each file field */
@@ -718,6 +716,19 @@ static void closeAllCursors(Vdbe *p){
p->nCursor = 0; p->nCursor = 0;
} }
/*
** Remove any elements that remain on the sorter for the VDBE given.
*/
static void SorterReset(Vdbe *p){
while( p->pSort ){
Sorter *pSorter = p->pSort;
p->pSort = pSorter->pNext;
sqliteFree(pSorter->zKey);
sqliteFree(pSorter->pData);
sqliteFree(pSorter);
}
}
/* /*
** Clean up the VM after execution. ** Clean up the VM after execution.
** **
@@ -738,25 +749,11 @@ static void Cleanup(Vdbe *p){
sqliteFree(p->aMem); sqliteFree(p->aMem);
p->aMem = 0; p->aMem = 0;
p->nMem = 0; p->nMem = 0;
for(i=0; i<p->nList; i++){ if( p->pList ){
KeylistFree(p->apList[i]); KeylistFree(p->pList);
p->apList[i] = 0; p->pList = 0;
} }
sqliteFree(p->apList); SorterReset(p);
p->apList = 0;
p->nList = 0;
for(i=0; i<p->nSort; i++){
Sorter *pSorter;
while( (pSorter = p->apSort[i])!=0 ){
p->apSort[i] = pSorter->pNext;
sqliteFree(pSorter->zKey);
sqliteFree(pSorter->pData);
sqliteFree(pSorter);
}
}
sqliteFree(p->apSort);
p->apSort = 0;
p->nSort = 0;
if( p->pFile ){ if( p->pFile ){
if( p->pFile!=stdin ) fclose(p->pFile); if( p->pFile!=stdin ) fclose(p->pFile);
p->pFile = 0; p->pFile = 0;
@@ -822,26 +819,25 @@ static char *zOpName[] = { 0,
"Rewind", "Next", "Destroy", "Clear", "Rewind", "Next", "Destroy", "Clear",
"CreateIndex", "CreateTable", "Reorganize", "BeginIdx", "CreateIndex", "CreateTable", "Reorganize", "BeginIdx",
"NextIdx", "PutIdx", "DeleteIdx", "MemLoad", "NextIdx", "PutIdx", "DeleteIdx", "MemLoad",
"MemStore", "ListOpen", "ListWrite", "ListRewind", "MemStore", "ListWrite", "ListRewind", "ListRead",
"ListRead", "ListClose", "SortOpen", "SortPut", "ListReset", "SortPut", "SortMakeRec", "SortMakeKey",
"SortMakeRec", "SortMakeKey", "Sort", "SortNext", "Sort", "SortNext", "SortCallback", "SortReset",
"SortKey", "SortCallback", "SortClose", "FileOpen", "FileOpen", "FileRead", "FileColumn", "FileClose",
"FileRead", "FileColumn", "FileClose", "AggReset", "AggReset", "AggFocus", "AggIncr", "AggNext",
"AggFocus", "AggIncr", "AggNext", "AggSet", "AggSet", "AggGet", "SetInsert", "SetFound",
"AggGet", "SetInsert", "SetFound", "SetNotFound", "SetNotFound", "SetClear", "MakeRecord", "MakeKey",
"SetClear", "MakeRecord", "MakeKey", "MakeIdxKey", "MakeIdxKey", "Goto", "If", "Halt",
"Goto", "If", "Halt", "ColumnCount", "ColumnCount", "ColumnName", "Callback", "NullCallback",
"ColumnName", "Callback", "NullCallback", "Integer", "Integer", "String", "Null", "Pop",
"String", "Null", "Pop", "Dup", "Dup", "Pull", "Add", "AddImm",
"Pull", "Add", "AddImm", "Subtract", "Subtract", "Multiply", "Divide", "Remainder",
"Multiply", "Divide", "Remainder", "BitAnd", "BitAnd", "BitOr", "BitNot", "ShiftLeft",
"BitOr", "BitNot", "ShiftLeft", "ShiftRight", "ShiftRight", "AbsValue", "Precision", "Min",
"AbsValue", "Precision", "Min", "Max", "Max", "Like", "Glob", "Eq",
"Like", "Glob", "Eq", "Ne", "Ne", "Lt", "Le", "Gt",
"Lt", "Le", "Gt", "Ge", "Ge", "IsNull", "NotNull", "Negative",
"IsNull", "NotNull", "Negative", "And", "And", "Or", "Not", "Concat",
"Or", "Not", "Concat", "Noop", "Noop", "Strlen", "Substr",
"Strlen", "Substr",
}; };
/* /*
@@ -3085,50 +3081,23 @@ case OP_Reorganize: {
break; break;
} }
/* Opcode: ListOpen P1 * * /* Opcode: ListWrite * * *
**
** Open a "List" structure used for temporary storage of integer
** record numbers. P1 will server as a handle to this list for future
** interactions. If another list with the P1 handle is
** already opened, the prior list is closed and a new one opened
** in its place.
*/
case OP_ListOpen: {
int i = pOp->p1;
VERIFY( if( i<0 ) goto bad_instruction; )
if( i>=p->nList ){
int j;
Keylist **apList = sqliteRealloc( p->apList, (i+1)*sizeof(Keylist*) );
if( apList==0 ){ goto no_mem; }
p->apList = apList;
for(j=p->nList; j<=i; j++) p->apList[j] = 0;
p->nList = i+1;
}else if( p->apList[i] ){
KeylistFree(p->apList[i]);
p->apList[i] = 0;
}
break;
}
/* Opcode: ListWrite P1 * *
** **
** Write the integer on the top of the stack ** Write the integer on the top of the stack
** into the temporary storage list P1. ** into the temporary storage list.
*/ */
case OP_ListWrite: { case OP_ListWrite: {
int i = pOp->p1;
Keylist *pKeylist; Keylist *pKeylist;
VERIFY( if( i<0 || i>=p->nList ) goto bad_instruction; )
VERIFY( if( p->tos<0 ) goto not_enough_stack; ) VERIFY( if( p->tos<0 ) goto not_enough_stack; )
pKeylist = p->apList[i]; pKeylist = p->pList;
if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){ if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){
pKeylist = sqliteMalloc( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) ); pKeylist = sqliteMalloc( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) );
if( pKeylist==0 ) goto no_mem; if( pKeylist==0 ) goto no_mem;
pKeylist->nKey = 1000; pKeylist->nKey = 1000;
pKeylist->nRead = 0; pKeylist->nRead = 0;
pKeylist->nUsed = 0; pKeylist->nUsed = 0;
pKeylist->pNext = p->apList[i]; pKeylist->pNext = p->pList;
p->apList[i] = pKeylist; p->pList = pKeylist;
} }
Integerify(p, p->tos); Integerify(p, p->tos);
pKeylist->aKey[pKeylist->nUsed++] = aStack[p->tos].i; pKeylist->aKey[pKeylist->nUsed++] = aStack[p->tos].i;
@@ -3136,28 +3105,24 @@ case OP_ListWrite: {
break; break;
} }
/* Opcode: ListRewind P1 * * /* Opcode: ListRewind * * *
** **
** Rewind the temporary buffer P1 back to the beginning. ** Rewind the temporary buffer back to the beginning.
*/ */
case OP_ListRewind: { case OP_ListRewind: {
int i = pOp->p1;
VERIFY( if( i<0 ) goto bad_instruction; )
/* This is now a no-op */ /* This is now a no-op */
break; break;
} }
/* Opcode: ListRead P1 P2 * /* Opcode: ListRead * P2 *
** **
** Attempt to read an integer from temporary storage buffer P1 ** Attempt to read an integer from the temporary storage buffer
** and push it onto the stack. If the storage buffer is empty, ** and push it onto the stack. If the storage buffer is empty,
** push nothing but instead jump to P2. ** push nothing but instead jump to P2.
*/ */
case OP_ListRead: { case OP_ListRead: {
int i = pOp->p1;
Keylist *pKeylist; Keylist *pKeylist;
VERIFY(if( i<0 || i>=p->nList ) goto bad_instruction;) pKeylist = p->pList;
pKeylist = p->apList[i];
if( pKeylist!=0 ){ if( pKeylist!=0 ){
VERIFY( VERIFY(
if( pKeylist->nRead<0 if( pKeylist->nRead<0
@@ -3170,7 +3135,7 @@ case OP_ListRead: {
aStack[p->tos].flags = STK_Int; aStack[p->tos].flags = STK_Int;
zStack[p->tos] = 0; zStack[p->tos] = 0;
if( pKeylist->nRead>=pKeylist->nUsed ){ if( pKeylist->nRead>=pKeylist->nUsed ){
p->apList[i] = pKeylist->pNext; p->pList = pKeylist->pNext;
sqliteFree(pKeylist); sqliteFree(pKeylist);
} }
}else{ }else{
@@ -3179,54 +3144,33 @@ case OP_ListRead: {
break; break;
} }
/* Opcode: ListClose P1 * * /* Opcode: ListReset * * *
** **
** Close the temporary storage buffer and discard its contents. ** Reset the temporary storage buffer so that it holds nothing.
*/ */
case OP_ListClose: { case OP_ListReset: {
int i = pOp->p1; if( p->pList ){
VERIFY( if( i<0 ) goto bad_instruction; ) KeylistFree(p->pList);
VERIFY( if( i>=p->nList ) goto bad_instruction; ) p->pList = 0;
KeylistFree(p->apList[i]);
p->apList[i] = 0;
break;
}
/* Opcode: SortOpen P1 * *
**
** Create a new sorter with index P1
*/
case OP_SortOpen: {
int i = pOp->p1;
VERIFY( if( i<0 ) goto bad_instruction; )
if( i>=p->nSort ){
int j;
Sorter **apSort = sqliteRealloc( p->apSort, (i+1)*sizeof(Sorter*) );
if( apSort==0 ){ goto no_mem; }
p->apSort = apSort;
for(j=p->nSort; j<=i; j++) p->apSort[j] = 0;
p->nSort = i+1;
} }
break; break;
} }
/* Opcode: SortPut P1 * * /* Opcode: SortPut * * *
** **
** The TOS is the key and the NOS is the data. Pop both from the stack ** The TOS is the key and the NOS is the data. Pop both from the stack
** and put them on the sorter. ** and put them on the sorter.
*/ */
case OP_SortPut: { case OP_SortPut: {
int i = pOp->p1;
int tos = p->tos; int tos = p->tos;
int nos = tos - 1; int nos = tos - 1;
Sorter *pSorter; Sorter *pSorter;
VERIFY( if( i<0 || i>=p->nSort ) goto bad_instruction; )
VERIFY( if( tos<1 ) goto not_enough_stack; ) VERIFY( if( tos<1 ) goto not_enough_stack; )
if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem; if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;
pSorter = sqliteMalloc( sizeof(Sorter) ); pSorter = sqliteMalloc( sizeof(Sorter) );
if( pSorter==0 ) goto no_mem; if( pSorter==0 ) goto no_mem;
pSorter->pNext = p->apSort[i]; pSorter->pNext = p->pSort;
p->apSort[i] = pSorter; p->pSort = pSorter;
pSorter->nKey = aStack[tos].n; pSorter->nKey = aStack[tos].n;
pSorter->zKey = zStack[tos]; pSorter->zKey = zStack[tos];
pSorter->nData = aStack[nos].n; pSorter->nData = aStack[nos].n;
@@ -3283,7 +3227,7 @@ case OP_SortMakeRec: {
break; break;
} }
/* Opcode: SortMakeKey P1 * P3 /* Opcode: SortMakeKey * * P3
** **
** Convert the top few entries of the stack into a sort key. The ** Convert the top few entries of the stack into a sort key. The
** number of stack entries consumed is the number of characters in ** number of stack entries consumed is the number of characters in
@@ -3330,59 +3274,54 @@ case OP_SortMakeKey: {
break; break;
} }
/* Opcode: Sort P1 * * /* Opcode: Sort * * *
** **
** Sort all elements on the given sorter. The algorithm is a ** Sort all elements on the sorter. The algorithm is a
** mergesort. ** mergesort.
*/ */
case OP_Sort: { case OP_Sort: {
int j; int i;
j = pOp->p1; Sorter *pElem;
VERIFY( if( j<0 ) goto bad_instruction; ) Sorter *apSorter[NSORT];
if( j<p->nSort ){ for(i=0; i<NSORT; i++){
int i; apSorter[i] = 0;
Sorter *pElem;
Sorter *apSorter[NSORT];
for(i=0; i<NSORT; i++){
apSorter[i] = 0;
}
while( p->apSort[j] ){
pElem = p->apSort[j];
p->apSort[j] = pElem->pNext;
pElem->pNext = 0;
for(i=0; i<NSORT-1; i++){
if( apSorter[i]==0 ){
apSorter[i] = pElem;
break;
}else{
pElem = Merge(apSorter[i], pElem);
apSorter[i] = 0;
}
}
if( i>=NSORT-1 ){
apSorter[NSORT-1] = Merge(apSorter[NSORT-1],pElem);
}
}
pElem = 0;
for(i=0; i<NSORT; i++){
pElem = Merge(apSorter[i], pElem);
}
p->apSort[j] = pElem;
} }
while( p->pSort ){
pElem = p->pSort;
p->pSort = pElem->pNext;
pElem->pNext = 0;
for(i=0; i<NSORT-1; i++){
if( apSorter[i]==0 ){
apSorter[i] = pElem;
break;
}else{
pElem = Merge(apSorter[i], pElem);
apSorter[i] = 0;
}
}
if( i>=NSORT-1 ){
apSorter[NSORT-1] = Merge(apSorter[NSORT-1],pElem);
}
}
pElem = 0;
for(i=0; i<NSORT; i++){
pElem = Merge(apSorter[i], pElem);
}
p->pSort = pElem;
break; break;
} }
/* Opcode: SortNext P1 P2 * /* Opcode: SortNext * P2 *
** **
** Push the data for the topmost element in the given sorter onto the ** Push the data for the topmost element in the sorter onto the
** stack, then remove the element from the sorter. ** stack, then remove the element from the sorter. If the sorter
** is empty, push nothing on the stack and instead jump immediately
** to instruction P2.
*/ */
case OP_SortNext: { case OP_SortNext: {
int i = pOp->p1; Sorter *pSorter = p->pSort;
VERIFY( if( i<0 ) goto bad_instruction; ) if( pSorter!=0 ){
if( VERIFY( i<p->nSort && ) p->apSort[i]!=0 ){ p->pSort = pSorter->pNext;
Sorter *pSorter = p->apSort[i];
p->apSort[i] = pSorter->pNext;
p->tos++; p->tos++;
VERIFY( NeedStack(p, p->tos); ) VERIFY( NeedStack(p, p->tos); )
zStack[p->tos] = pSorter->pData; zStack[p->tos] = pSorter->pData;
@@ -3396,28 +3335,7 @@ case OP_SortNext: {
break; break;
} }
#if 0 /* NOT USED */ /* Opcode: SortCallback * P2 *
/* Opcode: SortKey P1 * *
**
** Push the key for the topmost element of the sorter onto the stack.
** But don't change the sorter an any other way.
*/
case OP_SortKey: {
int i = pOp->p1;
VERIFY( if( i<0 ) goto bad_instruction; )
if( i<p->nSort && p->apSort[i]!=0 ){
Sorter *pSorter = p->apSort[i];
p->tos++;
VERIFY( NeedStack(p, p->tos); )
sqliteSetString(&zStack[p->tos], pSorter->zKey, 0);
aStack[p->tos].n = pSorter->nKey;
aStack[p->tos].flags = STK_Str|STK_Dyn;
}
break;
}
#endif /* NOT USED */
/* Opcode: SortCallback P1 P2 *
** **
** The top of the stack contains a callback record built using ** The top of the stack contains a callback record built using
** the SortMakeRec operation with the same P1 value as this ** the SortMakeRec operation with the same P1 value as this
@@ -3438,22 +3356,12 @@ case OP_SortCallback: {
break; break;
} }
/* Opcode: SortClose P1 * * /* Opcode: SortReset * * *
** **
** Close the given sorter and remove all its elements. ** Remove any elements that remain on the sorter.
*/ */
case OP_SortClose: { case OP_SortReset: {
Sorter *pSorter; SorterReset(p);
int i = pOp->p1;
VERIFY( if( i<0 ) goto bad_instruction; )
if( i<p->nSort ){
while( (pSorter = p->apSort[i])!=0 ){
p->apSort[i] = pSorter->pNext;
sqliteFree(pSorter->zKey);
sqliteFree(pSorter->pData);
sqliteFree(pSorter);
}
}
break; break;
} }

View File

@@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a ** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database. ** simple program to access and modify the underlying database.
** **
** $Id: vdbe.h,v 1.30 2001/10/19 16:44:57 drh Exp $ ** $Id: vdbe.h,v 1.31 2001/11/01 14:41:34 drh Exp $
*/ */
#ifndef _SQLITE_VDBE_H_ #ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_
@@ -111,95 +111,92 @@ typedef struct VdbeOp VdbeOp;
#define OP_MemLoad 36 #define OP_MemLoad 36
#define OP_MemStore 37 #define OP_MemStore 37
#define OP_ListOpen 38 #define OP_ListWrite 38
#define OP_ListWrite 39 #define OP_ListRewind 39
#define OP_ListRewind 40 #define OP_ListRead 40
#define OP_ListRead 41 #define OP_ListReset 41
#define OP_ListClose 42
#define OP_SortOpen 43 #define OP_SortPut 42
#define OP_SortPut 44 #define OP_SortMakeRec 43
#define OP_SortMakeRec 45 #define OP_SortMakeKey 44
#define OP_SortMakeKey 46 #define OP_Sort 45
#define OP_Sort 47 #define OP_SortNext 46
#define OP_SortNext 48 #define OP_SortCallback 47
#define OP_SortKey 49 #define OP_SortReset 48
#define OP_SortCallback 50
#define OP_SortClose 51
#define OP_FileOpen 52 #define OP_FileOpen 49
#define OP_FileRead 53 #define OP_FileRead 50
#define OP_FileColumn 54 #define OP_FileColumn 51
#define OP_FileClose 55 #define OP_FileClose 52
#define OP_AggReset 56 #define OP_AggReset 53
#define OP_AggFocus 57 #define OP_AggFocus 54
#define OP_AggIncr 58 #define OP_AggIncr 55
#define OP_AggNext 59 #define OP_AggNext 56
#define OP_AggSet 60 #define OP_AggSet 57
#define OP_AggGet 61 #define OP_AggGet 58
#define OP_SetInsert 62 #define OP_SetInsert 59
#define OP_SetFound 63 #define OP_SetFound 60
#define OP_SetNotFound 64 #define OP_SetNotFound 61
#define OP_SetClear 65 #define OP_SetClear 62
#define OP_MakeRecord 66 #define OP_MakeRecord 63
#define OP_MakeKey 67 #define OP_MakeKey 64
#define OP_MakeIdxKey 68 #define OP_MakeIdxKey 65
#define OP_Goto 69 #define OP_Goto 66
#define OP_If 70 #define OP_If 67
#define OP_Halt 71 #define OP_Halt 68
#define OP_ColumnCount 72 #define OP_ColumnCount 69
#define OP_ColumnName 73 #define OP_ColumnName 70
#define OP_Callback 74 #define OP_Callback 71
#define OP_NullCallback 75 #define OP_NullCallback 72
#define OP_Integer 76 #define OP_Integer 73
#define OP_String 77 #define OP_String 74
#define OP_Null 78 #define OP_Null 75
#define OP_Pop 79 #define OP_Pop 76
#define OP_Dup 80 #define OP_Dup 77
#define OP_Pull 81 #define OP_Pull 78
#define OP_Add 82 #define OP_Add 79
#define OP_AddImm 83 #define OP_AddImm 80
#define OP_Subtract 84 #define OP_Subtract 81
#define OP_Multiply 85 #define OP_Multiply 82
#define OP_Divide 86 #define OP_Divide 83
#define OP_Remainder 87 #define OP_Remainder 84
#define OP_BitAnd 88 #define OP_BitAnd 85
#define OP_BitOr 89 #define OP_BitOr 86
#define OP_BitNot 90 #define OP_BitNot 87
#define OP_ShiftLeft 91 #define OP_ShiftLeft 88
#define OP_ShiftRight 92 #define OP_ShiftRight 89
#define OP_AbsValue 93 #define OP_AbsValue 90
#define OP_Precision 94 #define OP_Precision 91
#define OP_Min 95 #define OP_Min 92
#define OP_Max 96 #define OP_Max 93
#define OP_Like 97 #define OP_Like 94
#define OP_Glob 98 #define OP_Glob 95
#define OP_Eq 99 #define OP_Eq 96
#define OP_Ne 100 #define OP_Ne 97
#define OP_Lt 101 #define OP_Lt 98
#define OP_Le 102 #define OP_Le 99
#define OP_Gt 103 #define OP_Gt 100
#define OP_Ge 104 #define OP_Ge 101
#define OP_IsNull 105 #define OP_IsNull 102
#define OP_NotNull 106 #define OP_NotNull 103
#define OP_Negative 107 #define OP_Negative 104
#define OP_And 108 #define OP_And 105
#define OP_Or 109 #define OP_Or 106
#define OP_Not 110 #define OP_Not 107
#define OP_Concat 111 #define OP_Concat 108
#define OP_Noop 112 #define OP_Noop 109
#define OP_Strlen 113 #define OP_Strlen 110
#define OP_Substr 114 #define OP_Substr 111
#define OP_MAX 114 #define OP_MAX 111
/* /*
** Prototypes for the VDBE interface. See comments on the implementation ** Prototypes for the VDBE interface. See comments on the implementation

View File

@@ -19,6 +19,10 @@ proc chng {date desc} {
chng {2001 Oct ?? (2.0.8)} { chng {2001 Oct ?? (2.0.8)} {
<li>Documentation updates</li> <li>Documentation updates</li>
<li>Simplify the design of the VDBE by restricting the number of sorters
and lists to 1.
In practice, no more than one sorter and one list was every used anyhow.
</li>
} }
chng {2001 Oct 21 (2.0.7)} { chng {2001 Oct 21 (2.0.7)} {

View File

@@ -1,7 +1,7 @@
# #
# Run this TCL script to generate HTML for the index.html file. # Run this TCL script to generate HTML for the index.html file.
# #
set rcsid {$Id: index.tcl,v 1.45 2001/10/31 15:44:47 drh Exp $} set rcsid {$Id: index.tcl,v 1.46 2001/11/01 14:41:34 drh Exp $}
puts {<html> puts {<html>
<head><title>SQLite: An SQL Database Engine In A C Library</title></head> <head><title>SQLite: An SQL Database Engine In A C Library</title></head>
@@ -16,7 +16,7 @@ puts {</p>}
puts {<h2>Introduction</h2> puts {<h2>Introduction</h2>
<p>SQLite is a C library that implements an SQL database engine. <p>SQLite is a C library that implements an embeddable SQL database engine.
Programs that link with the SQLite library can have SQL database Programs that link with the SQLite library can have SQL database
access without running a separate RDBMS process. access without running a separate RDBMS process.
The distribution comes with a standalone command-line The distribution comes with a standalone command-line
@@ -64,8 +64,10 @@ puts {<h2>Current Status</h2>
<p>A <a href="changes.html">change history</a> is available online. <p>A <a href="changes.html">change history</a> is available online.
The latest source code is The latest source code is
<a href="download.html">available for download</a>. <a href="download.html">available for download</a>.
There are currently no <em>known</em> memory leaks or debilitating bugs There are currently no known memory leaks or bugs
in the library. in the library.
SQLite is currently being used in several mission-critical
applications.
</p> </p>
<p> <p>
@@ -158,32 +160,6 @@ $ make test <i> Optional: run regression tests </i>
</pre></blockquote> </pre></blockquote>
} }
puts {<h2>Command-line Usage Example</h2>
<p>Download the source archive and compile the <b>sqlite</b>
program as described above. Then type:</p>
<blockquote><pre>
bash$ sqlite ~/newdb <i>Directory ~/newdb created automatically</i>
sqlite> create table t1(
...> a int,
...> b varchar(20)
...> c text
...> ); <i>End each SQL statement with a ';'</i>
sqlite> insert into t1
...> values(1,'hi','y''all');
sqlite> select * from t1;
1|hello|world
sqlite> .mode columns <i>Special commands begin with '.'</i>
sqlite> .header on <i>Type ".help" for a list of commands</i>
sqlite> select * from t1;
a b c
------ ------- -------
1 hi y'all
sqlite> .exit
base$
</pre></blockquote>
}
puts {<h2>Related Sites</h2> puts {<h2>Related Sites</h2>
<ul> <ul>

View File

@@ -1,7 +1,7 @@
# #
# Run this Tcl script to generate the sqlite.html file. # Run this Tcl script to generate the sqlite.html file.
# #
set rcsid {$Id: opcode.tcl,v 1.6 2001/09/28 23:11:24 drh Exp $} set rcsid {$Id: opcode.tcl,v 1.7 2001/11/01 14:41:34 drh Exp $}
puts {<html> puts {<html>
<head> <head>
@@ -117,22 +117,18 @@ Each memory location can hold an arbitrary string. The memory
cells are typically used to hold the result of a scalar SELECT cells are typically used to hold the result of a scalar SELECT
that is part of a larger expression.</p> that is part of a larger expression.</p>
<p>The virtual machine contains an arbitrary number of sorters. <p>The virtual machine contains a single sorter.
Each sorter is able to accumulate records, sort those records, The sorter is able to accumulate records, sort those records,
then play the records back in sorted order. Sorters are used then play the records back in sorted order. The sorter is used
to implement the ORDER BY clause of a SELECT statement. The to implement the ORDER BY clause of a SELECT statement.</p>
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.</p>
<p>The virtual machine may contain an arbitrary number of "Lists". <p>The virtual machine contains a single "Lists".
Each list stores a list of integers. Lists are used to hold the The list stores a list of integers. Lists are used to hold the
rowids for records of a database table that needs to be modified. rowids for records of a database table that needs to be modified.
The WHERE clause of an UPDATE or DELETE statement scans through The WHERE clause of an UPDATE or DELETE statement scans through
the table and writes the rowid 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 into the 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 in a separate step.</p>
making a change to a database table can alter the scan order.</p>
<p>The virtual machine can contain an arbitrary number of "Sets". <p>The virtual machine can contain an arbitrary number of "Sets".
Each set holds an arbitrary number of strings. Sets are used to Each set holds an arbitrary number of strings. Sets are used to