diff --git a/manifest b/manifest
index 129fa8c22e..a5fe5d7d0f 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C fix\sparser\sstack\soverflow\s(CVS\s119)
-D 2000-08-01T09:56:27
+C file\sformat\schange\s(CVS\s120)
+D 2000-08-02T12:26:29
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
F Makefile.in 670aa9413cb2cdcded23b328a9e255c845c41a1e
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
@@ -7,7 +7,7 @@ F configure 51063d594190fa085f909cefc9427241088bec4f x
F configure.in a04f02ba61ed09a00e862b4f78b91b06a559e0b5
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
F src/build.c ecb8ec724914780efed01d1739e6dd398d75af46
-F src/dbbe.c 1bc12590063a21e6098503b5821df87da20c1d8f
+F src/dbbe.c 5c69d68fe8d9461e56d066f9a7f693636c02d0c7
F src/dbbe.h 8718b718b36d37584e9bbdfccec10588fa91271f
F src/delete.c 4d491eaf61b515516749c7ed68fa3b2ee8a09065
F src/expr.c 2fa63f086707176d09092e71832f9bbdc6a8ac85
@@ -17,12 +17,12 @@ F src/parse.y 5d199034de5d29ebedb42c1c51f34db4df40cbe5
F src/select.c d382e96c2221d08367cc87976f2b574537c9de97
F src/shell.c a5eb8ee9d5f90e735900a92e7fc364a54deb2cfb
F src/sqlite.h 82ae53028e27919250f886ff9d7c4927de81978a
-F src/sqliteInt.h 74eb0e266e05d10278e2c20a2cd8fe9fd9fa0d1a
+F src/sqliteInt.h cbb973ffcbbefdfb59438fa5c1df0be768cc490c
F src/tclsqlite.c 9f358618ae803bedf4fb96da5154fd45023bc1f7
F src/tokenize.c 77ff8164a8751994bc9926ce282847f653ac0c16
F src/update.c 51b9ef7434b15e31096155da920302e9db0d27fc
F src/util.c b75b33e6bd5d47898bb7ed9fdd0dea4fe7c19b00
-F src/vdbe.c 4308e226d5b33a72dfe2c88a44eb0a63381fe24b
+F src/vdbe.c bdedf21230581f0cf73a2dcd8fe23f30cf30ebe6
F src/vdbe.h 6c5653241633c583549c2d8097394ab52550eb63
F src/where.c 420f666a38b405cd58bd7af832ed99f1dbc7d336
F test/all.test 0950c135cab7e60c07bd745ccfad1476211e5bd7
@@ -31,7 +31,7 @@ F test/dbbe.test 0a8e4293cf816e590dcbb01be4cd4e8f7f95bdc8
F test/delete.test 402ee3ccb6e544582d24c573ef70b34d09583ae7
F test/expr.test 09b55ccf81cb8cc2f9cd83d592a2ba187ee48ba8
F test/in.test 2c560c0f55fb777029fd9bb5378f2997582aa603
-F test/index.test 620ceab7165dd078d1266bdc2cac6147f04534ac
+F test/index.test e5f4e7ad41e1709ef4426a3a4ce1bafe1afe1ee4
F test/insert.test 66f4c3bd600fec8eb1e733b928cbe6fa885eff0c
F test/insert2.test 732405e30331635af8d159fccabe835eea5cd0c6
F test/lock.test 42a2d171eba1078cf3fd58ab64241eb8f1b08d69
@@ -59,16 +59,16 @@ F www/arch.fig 4e26e9dca3c49724fc8f554c695ddea9f2413156
F www/arch.png c4d908b79065a72e7dcf19317f36d1324c550e87
F www/arch.tcl 4f6a9afecc099a27bba17b4f8cc9561abc15dc40
F www/c_interface.tcl 29593cf77025bab137b7ba64b9459eb5eb6b4873
-F www/changes.tcl bfd60af0af1cd81030a14dd072fb0214f44b1470
+F www/changes.tcl 0fe8d43635dd08a01479774520f54149550cdb74
F www/crosscompile.tcl 19734ce7f18b16ff2ed8479412abf8aca56e1dcc
-F www/fileformat.tcl f3a70650e942262f8285d53097d48f0b3aa59862
-F www/index.tcl 8043911df3baacc5be42c40c9bd0883602e8a63a
+F www/fileformat.tcl 1c353d202cc75de55a916a1bab80e7b3cc5660ee
+F www/index.tcl ae93e74540d9198743009fe5a60b7c2c2e7885d6
F www/lang.tcl 1645e9107d75709be4c6099b643db235bbe0a151
F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60
F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
F www/sqlite.tcl 69781eaffb02e17aa4af28b76a2bedb19baa8e9f
F www/vdbe.tcl bcbfc33bcdd0ebad95eab31286adb9e1bc289520
-P 4132d4760f6a2cbcf853f82546987d932e76e3c1
-R 463a993a466cf480cd166cfd852b8351
+P bffca90f37a69c5bd26b719a964408e0e518a7dc
+R fb9083cf992b9bf32aa0798cc17db2e1
U drh
-Z 9d9beee969b260700b91790c5774a3ef
+Z b90780147dd290d806a672cbfe65d916
diff --git a/manifest.uuid b/manifest.uuid
index ad28fd3e93..fb116ff964 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-bffca90f37a69c5bd26b719a964408e0e518a7dc
\ No newline at end of file
+67f8af377c8a92ac155f55afc75e9957bec4e787
\ No newline at end of file
diff --git a/src/dbbe.c b/src/dbbe.c
index 48c37ba388..e34ffd91d6 100644
--- a/src/dbbe.c
+++ b/src/dbbe.c
@@ -30,7 +30,7 @@
** relatively simple to convert to a different database such
** as NDBM, SDBM, or BerkeleyDB.
**
-** $Id: dbbe.c,v 1.17 2000/07/31 13:38:26 drh Exp $
+** $Id: dbbe.c,v 1.18 2000/08/02 12:26:29 drh Exp $
*/
#include "sqliteInt.h"
#include
@@ -629,6 +629,7 @@ int sqliteDbbeNew(DbbeCursor *pCursr){
for(i=0; i<4; i++){
iKey = (iKey<<8) + rc4byte(pRc4);
}
+ if( iKey==0 ) continue;
key.dptr = (char*)&iKey;
key.dsize = 4;
go = gdbm_exists(pCursr->pFile->dbf, key);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 1b84eb1167..ae67ac479c 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -23,7 +23,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.27 2000/07/29 13:06:59 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.28 2000/08/02 12:26:29 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
@@ -123,7 +123,7 @@ struct sqlite {
Dbbe *pBe; /* The backend driver */
int flags; /* Miscellanous flags */
void *pBusyArg; /* 1st Argument to the busy callback */
- int (*xBusyCallback)(void *,const char*,int);
+ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */
Table *apTblHash[N_HASH]; /* All tables of the database */
Index *apIdxHash[N_HASH]; /* All indices of the database */
};
diff --git a/src/vdbe.c b/src/vdbe.c
index 34240b7d3d..4850506855 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.37 2000/07/30 20:04:43 drh Exp $
+** $Id: vdbe.c,v 1.38 2000/08/02 12:26:29 drh Exp $
*/
#include "sqliteInt.h"
#include
@@ -2143,17 +2143,23 @@ int sqliteVdbeExec(
if( i>=0 && inCursor && (pCrsr = p->aCsr[i].pCursor)!=0 ){
int *aIdx;
int nIdx;
- int j;
+ int j, k;
nIdx = sqliteDbbeDataLength(pCrsr)/sizeof(int);
aIdx = (int*)sqliteDbbeReadData(pCrsr, 0);
- for(j=p->aCsr[i].index; j1 ){
+ k = *(aIdx++);
+ if( k>nIdx-1 ) k = nIdx-1;
+ }else{
+ k = nIdx;
+ }
+ for(j=p->aCsr[i].index; jaStack[tos].i = aIdx[j];
p->aStack[tos].flags = STK_Int;
break;
}
}
- if( j>=nIdx ){
+ if( j>=k ){
j = -1;
pc = pOp->p2 - 1;
PopStack(p, 1);
@@ -2193,14 +2199,38 @@ int sqliteVdbeExec(
/* Extend the existing record */
int nIdx;
int *aIdx;
+ int k;
+
nIdx = sqliteDbbeDataLength(pCrsr)/sizeof(int);
- aIdx = sqliteMalloc( sizeof(int)*(nIdx+1) );
- if( aIdx==0 ) goto no_mem;
- sqliteDbbeCopyData(pCrsr, 0, nIdx*sizeof(int), (char*)aIdx);
- aIdx[nIdx] = newVal;
- sqliteDbbePut(pCrsr, p->aStack[tos].n, p->zStack[tos],
- sizeof(int)*(nIdx+1), (char*)aIdx);
- sqliteFree(aIdx);
+ if( nIdx==1 ){
+ aIdx = sqliteMalloc( sizeof(int)*4 );
+ if( aIdx==0 ) goto no_mem;
+ aIdx[0] = 2;
+ sqliteDbbeCopyData(pCrsr, 0, sizeof(int), (char*)&aIdx[1]);
+ aIdx[2] = newVal;
+ sqliteDbbePut(pCrsr, p->aStack[tos].n, p->zStack[tos],
+ sizeof(int)*4, (char*)aIdx);
+ sqliteFree(aIdx);
+ }else{
+ aIdx = (int*)sqliteDbbeReadData(pCrsr, 0);
+ k = aIdx[0];
+ if( kaStack[tos].n, p->zStack[tos],
+ sizeof(int)*nIdx, (char*)aIdx);
+ }else{
+ nIdx *= 2;
+ aIdx = sqliteMalloc( sizeof(int)*nIdx );
+ if( aIdx==0 ) goto no_mem;
+ sqliteDbbeCopyData(pCrsr, 0, sizeof(int)*(k+1), (char*)aIdx);
+ aIdx[k+1] = newVal;
+ aIdx[0]++;
+ sqliteDbbePut(pCrsr, p->aStack[tos].n, p->zStack[tos],
+ sizeof(int)*nIdx, (char*)aIdx);
+ sqliteFree(aIdx);
+ }
+ }
}
}
PopStack(p, 2);
@@ -2229,7 +2259,7 @@ int sqliteVdbeExec(
if( i>=0 && inCursor && (pCrsr = p->aCsr[i].pCursor)!=0 ){
int *aIdx;
int nIdx;
- int j;
+ int j, k;
int r;
int oldVal;
Integerify(p, nos);
@@ -2239,14 +2269,20 @@ int sqliteVdbeExec(
if( r==0 ) break;
nIdx = sqliteDbbeDataLength(pCrsr)/sizeof(int);
aIdx = (int*)sqliteDbbeReadData(pCrsr, 0);
- for(j=0; j=nIdx ) break;
- aIdx[j] = aIdx[nIdx-1];
- if( nIdx==1 ){
+ if( (nIdx==1 && aIdx[0]==oldVal) || (aIdx[0]==1 && aIdx[1]==oldVal) ){
sqliteDbbeDelete(pCrsr, p->aStack[tos].n, p->zStack[tos]);
}else{
+ k = aIdx[0];
+ for(j=1; j<=k && aIdx[j]!=oldVal; j++){}
+ if( j>k ) break;
+ aIdx[j] = aIdx[k];
+ aIdx[k] = 0;
+ aIdx[0]--;
+ if( aIdx[0]*3 + 1 < nIdx ){
+ nIdx /= 2;
+ }
sqliteDbbePut(pCrsr, p->aStack[tos].n, p->zStack[tos],
- sizeof(int)*(nIdx-1), (char*)aIdx);
+ sizeof(int)*nIdx, (char*)aIdx);
}
}
PopStack(p, 2);
diff --git a/test/index.test b/test/index.test
index 47b14ee3a1..b72c556432 100644
--- a/test/index.test
+++ b/test/index.test
@@ -23,7 +23,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the CREATE INDEX statement.
#
-# $Id: index.test,v 1.5 2000/06/17 13:12:40 drh Exp $
+# $Id: index.test,v 1.6 2000/08/02 12:26:30 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -281,11 +281,51 @@ do_test index-10.2 {
SELECT b FROM t1 WHERE a=1 ORDER BY b;
}
} {2}
-do_test index-10.2 {
+do_test index-10.3 {
execsql {
DELETE FROM t1 WHERE b=2;
SELECT b FROM t1 WHERE a=1 ORDER BY b;
}
} {}
+do_test index-10.4 {
+ execsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES (1,1);
+ INSERT INTO t1 VALUES (1,2);
+ INSERT INTO t1 VALUES (1,3);
+ INSERT INTO t1 VALUES (1,4);
+ INSERT INTO t1 VALUES (1,5);
+ INSERT INTO t1 VALUES (1,6);
+ INSERT INTO t1 VALUES (1,7);
+ INSERT INTO t1 VALUES (1,8);
+ INSERT INTO t1 VALUES (1,9);
+ INSERT INTO t1 VALUES (2,0);
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {1 2 3 4 5 6 7 8 9}
+do_test index-10.5 {
+ execsql {
+ DELETE FROM t1 WHERE b IN (2, 4, 6, 8);
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {1 3 5 7 9}
+do_test index-10.6 {
+ execsql {
+ DELETE FROM t1 WHERE b>2;
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {1}
+do_test index-10.7 {
+ execsql {
+ DELETE FROM t1 WHERE b=1;
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {}
+do_test index-10.8 {
+ execsql {
+ SELECT b FROM t1 ORDER BY b;
+ }
+} {0}
+
finish_test
diff --git a/www/changes.tcl b/www/changes.tcl
index 012447ec17..c16b46cdf2 100644
--- a/www/changes.tcl
+++ b/www/changes.tcl
@@ -17,6 +17,13 @@ proc chng {date desc} {
puts "
"
}
+chng {2000 Aug 2} {
+The file format for indices was changed slightly in order to work
+ around an inefficiency that can sometimes come up with GDBM when
+ there are large indices having many entries with the same key.
+ ** Incompatible Change **
+}
+
chng {2000 Aug 1} {
The parser's stack was overflowing on a very long UPDATE statement.
This is now fixed.
diff --git a/www/fileformat.tcl b/www/fileformat.tcl
index 203aab3586..d519e8d0e5 100644
--- a/www/fileformat.tcl
+++ b/www/fileformat.tcl
@@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the fileformat.html file.
#
-set rcsid {$Id: fileformat.tcl,v 1.2 2000/06/23 17:02:09 drh Exp $}
+set rcsid {$Id: fileformat.tcl,v 1.3 2000/08/02 12:26:30 drh Exp $}
puts {
@@ -109,11 +109,11 @@ sqlite> (((insert into t1 values(10,NULL,'hello!');)))
sqlite> (((insert into t1 values(-11,'this is','a test');)))
sqlite> (((.exit)))
$ (((gdbmdump ex1/t1.tbl)))
-key : 223100ae "1..
+key : 6d1a6e03 m.n.
data : 0c000000 10000000 18000000 2d313100 74686973 ............-11.this
20697300 61207465 737400 is.a test.
-key : a840e996 .@..
+key : 6d3f90e2 m?..
data : 0c000000 00000000 0f000000 31300068 656c6c6f ............10.hello
2100 !.
@@ -151,7 +151,12 @@ table that is being indexed. The GDBM key is an
arbitrary length null-terminated string which is SQL key that
is used by the index. The data is a list of integers that correspond
to GDBM keys of entries in data table that have the corresponding
-SQL key.
+SQL key. If the data record of the index is exactly 4 bytes in size,
+then the data represents a single integer key. If the data is greater
+than 4 bytes in size, then the first 4 bytes form an integer that
+tells us how many keys are in the data. The index data record is
+always sized to be a power of 2. Unused slots at the end of the
+index data record are filled with zero.
To illustrate, we will create an index on the example table
shown above, and add a new entry to this table that has a duplicate
@@ -191,10 +196,10 @@ GDBM key.
Code {
$ (((gdbmdump ex1/i1.tbl)))
key : 313000 10.
-data : a840e996 c19e3119 .@....1.
+data : 02000000 45b4f724 6d3f90e2 00000000 ....E..$m?......
key : 2d313100 -11.
-data : 223100ae "1..
+data : 6d1a6e03 m.n.
$
}
@@ -207,6 +212,11 @@ are just the text values for a columns of table t1.
The data for each record of the index is a list of integers
where each integer is the GDBM key for an entry in the t1
table that has the corresponding value for the a column.
+The index entry for -11 contains only a single entry and is 4
+bytes in size. The index entry for 10 is 16 bytes in size but
+contains only 2 entries. The first integer is the number of
+entires. The two integer keys follow. The last 4 bytes unused
+and are set to zero.
}
puts {
diff --git a/www/index.tcl b/www/index.tcl
index 5dc4f6fd1d..ad48ed56d9 100644
--- a/www/index.tcl
+++ b/www/index.tcl
@@ -1,7 +1,7 @@
#
# Run this TCL script to generate HTML for the index.html file.
#
-set rcsid {$Id: index.tcl,v 1.22 2000/08/01 09:56:27 drh Exp $}
+set rcsid {$Id: index.tcl,v 1.23 2000/08/02 12:26:30 drh Exp $}
puts {
SQLite: An SQL Database Engine Built Atop GDBM
@@ -13,23 +13,6 @@ puts "This page was last modified on [lrange $rcsid 3 4] GMT
"
puts "The SQLite source code was last modifed on [exec cat last_change] GMT"
puts {}
-if 0 {
-puts {
-News
-
-The SQLite code base is being called "beta" only because it is
-relatively new. It appears to be stable and usable.
-Most of the SQL language is now implemented and working.
-The regression test suite
-provides good coverage, according to
-gcov.
-There are currently no known errors in the code.
-
-If you find bugs or missing features, please submit a comment
-to the SQLite mailing list.
-}
-}
-
puts {Introduction
SQLite is an SQL database engine built on top of the
@@ -41,6 +24,25 @@ that can be linked
with a C/C++ program to provide SQL database access without
an separate RDBMS.
+Important News Flash!
+
+The SQLite file format was changed in an incompatible way on
+Aug 2, 2000. If you are updated the library and have databases
+built using the old version of the library, you should save your
+old databases into an ASCII fileformat then reimport those
+database using the new library. For example, if you change the
+name of the old sqlite utility to "old-sqlite" and
+change the name of the old database directory to "old-db", then
+you can reconstruct the database as follows:
+
+
+echo .dump | old-sqlite old-db | sqlite db
+
+
+This file format change was made to work around a potential
+inefficiency in GDBM that comes up when large indices are created
+on tables where many entries in the table have the same key.
+
Features