1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Changes to the DBBE. Moving toward having many more

backend driver choices. (CVS 176)

FossilOrigin-Name: c0730217a04323a1a73d125e3e7da32bcc8d58fc
This commit is contained in:
drh
2001-01-13 14:34:05 +00:00
parent 993c2a7c8f
commit ae85dc8b0b
12 changed files with 384 additions and 433 deletions

View File

@ -48,8 +48,8 @@ LIBREADLINE = @TARGET_READLINE_LIBS@
# Object files for the SQLite library. # Object files for the SQLite library.
# #
LIBOBJ = build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \ LIBOBJ = build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \
main.o parse.o printf.o select.o table.o tokenize.o update.o \ main.o parse.o printf.o random.o select.o table.o tokenize.o \
util.o vdbe.o where.o tclsqlite.o update.o util.o vdbe.o where.o tclsqlite.o
# All of the source code files. # All of the source code files.
# #
@ -66,6 +66,7 @@ SRC = \
$(TOP)/src/main.c \ $(TOP)/src/main.c \
$(TOP)/src/parse.y \ $(TOP)/src/parse.y \
$(TOP)/src/printf.c \ $(TOP)/src/printf.c \
$(TOP)/src/random.c \
$(TOP)/src/select.c \ $(TOP)/src/select.c \
$(TOP)/src/shell.c \ $(TOP)/src/shell.c \
$(TOP)/src/sqlite.h.in \ $(TOP)/src/sqlite.h.in \
@ -162,6 +163,9 @@ expr.o: $(TOP)/src/expr.c $(HDR)
insert.o: $(TOP)/src/insert.c $(HDR) insert.o: $(TOP)/src/insert.c $(HDR)
$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/insert.c $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/insert.c
random.o: $(TOP)/src/random.c $(HDR)
$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/random.c
select.o: $(TOP)/src/select.c $(HDR) select.o: $(TOP)/src/select.c $(HDR)
$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/select.c $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/select.c

View File

@ -1 +1 @@
1.0.18 1.1.0

View File

@ -1,34 +1,35 @@
C Version\s1.0.18\s(CVS\s485) C Changes\sto\sthe\sDBBE.\s\sMoving\stoward\shaving\smany\smore\nbackend\sdriver\schoices.\s(CVS\s176)
D 2001-01-04T14:30:00 D 2001-01-13T14:34:06
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
F Makefile.in 0b1fdafa55e1bf4d3a4f5213544130e66ef32052 F Makefile.in 7efa81e2985b45ba73db27d55b70cc927f5abfd7
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
F VERSION 049adaa0a3c5ffae5eb0267c11c84b9b206a550d F VERSION 05e17b646a817240c206186f94f8f4c70974d5dc
F configure 3dc1edb9dcf60215e31ff72b447935ab62211442 x F configure 3dc1edb9dcf60215e31ff72b447935ab62211442 x
F configure.in d892ca33db7e88a055519ce2f36dcb11020e8fff F configure.in d892ca33db7e88a055519ce2f36dcb11020e8fff
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47 F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
F src/build.c e2ceba852dc45ca899e68a042b29c3daab011575 F src/build.c e2ceba852dc45ca899e68a042b29c3daab011575
F src/dbbe.c 7e01384320075bf1d3e7fb54984df73435908809 F src/dbbe.c 50e97d6dced263ce55ee992905a68dd65d15f9e8
F src/dbbe.h d175a04b35ea75078274e059dcbcbf7c1262d42a F src/dbbe.h c447dad03396ab7da690ba7b31dd37cb30cd64af
F src/dbbegdbm.c 4ac7222afff0cf91014803f8791740b6da825a2b F src/dbbegdbm.c 9684095a11a2aad60322df0084d7e6cae3509ecc
F src/dbbemem.c b55faed2e4719db47ade3483e85f7cb4b5fad39a F src/dbbemem.c f443a831e131eaf4e344ee96b3f52fec22cf04e0
F src/delete.c 4d491eaf61b515516749c7ed68fa3b2ee8a09065 F src/delete.c 4d491eaf61b515516749c7ed68fa3b2ee8a09065
F src/expr.c 7d7646afd52d1448237e5f517454cfb2d3d394d6 F src/expr.c 7d7646afd52d1448237e5f517454cfb2d3d394d6
F src/insert.c f146f149ad2422a1dc3bfa7a1651a25940f98958 F src/insert.c f146f149ad2422a1dc3bfa7a1651a25940f98958
F src/main.c 52355458131977c1ac40a006ce2fe2035f39069c F src/main.c 340e5b04ce1222e4a75df7cb96bc2d0a236e881c
F src/parse.y 25ee4d8efccc4b247c32fe4ab194e3dd8fd5a4ee F src/parse.y 25ee4d8efccc4b247c32fe4ab194e3dd8fd5a4ee
F src/printf.c 1efb6b3e7f28a93be57132de3f8f400d2ac1460e F src/printf.c 1efb6b3e7f28a93be57132de3f8f400d2ac1460e
F src/random.c 3dc42fb35d834901577aa547308ff3c8941fea25
F src/select.c c1de8ac34131324fa05664b06b0ae1ee9c02905d F src/select.c c1de8ac34131324fa05664b06b0ae1ee9c02905d
F src/shell.c 441e20913cde0bb71281f4027623c623530241cd F src/shell.c 441e20913cde0bb71281f4027623c623530241cd
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in fd86903777f1ee7bd0465243224a0fd2100eedc8 F src/sqlite.h.in fd86903777f1ee7bd0465243224a0fd2100eedc8
F src/sqliteInt.h ed06214fc7054e43182ac351ebde913ede708639 F src/sqliteInt.h c5d2cc9ab270c24d6f7d705b03c801135b50fb39
F src/table.c 5be76051a8ed6f6bfa641f4adc52529efa34fbf9 F src/table.c 5be76051a8ed6f6bfa641f4adc52529efa34fbf9
F src/tclsqlite.c 178adf318eab2ff480c288a87541d4ab1c37d985 F src/tclsqlite.c 178adf318eab2ff480c288a87541d4ab1c37d985
F src/tokenize.c 6843f1d7a5d2ee08ceb10bdecfcc8684131ffcf7 F src/tokenize.c 6843f1d7a5d2ee08ceb10bdecfcc8684131ffcf7
F src/update.c 51b9ef7434b15e31096155da920302e9db0d27fc F src/update.c 51b9ef7434b15e31096155da920302e9db0d27fc
F src/util.c 0298100e6427a4b644f767ede12276fa7170fbb6 F src/util.c 0298100e6427a4b644f767ede12276fa7170fbb6
F src/vdbe.c 3ddd7e3d17c954fc50afd5e73898371da09ad1c6 F src/vdbe.c 46abf920b03a33e724c23049ab4017703ba18e28
F src/vdbe.h 140cdec3c56f70483e169f8ae657bd90f9fd6e98 F src/vdbe.h 140cdec3c56f70483e169f8ae657bd90f9fd6e98
F src/where.c 3dfad2ffd0aa994d5eceac88852f7189c8d1d3c8 F src/where.c 3dfad2ffd0aa994d5eceac88852f7189c8d1d3c8
F test/all.test 15cac2f6b2d4c55bf896212aff3cc9d6597b0490 F test/all.test 15cac2f6b2d4c55bf896212aff3cc9d6597b0490
@ -76,7 +77,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2 F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
P 81815a9c30ffc803cc03aad98936cba641674cd8 P 46b86abb1cc8e550acddba24e510d36eaf8ac6b9
R bf70551a041afaf128f504c8472d7ba7 R 1d32d650ba38f8b6672c17c49e299816
U drh U drh
Z 2ae1ca5ad1f48067a5d45adf3cf7ab78 Z d3d2bca8c08f700ef95bd56e0b8b1082

View File

@ -1 +1 @@
46b86abb1cc8e550acddba24e510d36eaf8ac6b9 c0730217a04323a1a73d125e3e7da32bcc8d58fc

View File

@ -30,7 +30,7 @@
** relatively simple to convert to a different database such ** relatively simple to convert to a different database such
** as NDBM, SDBM, or BerkeleyDB. ** as NDBM, SDBM, or BerkeleyDB.
** **
** $Id: dbbe.c,v 1.21 2000/10/19 14:10:09 drh Exp $ ** $Id: dbbe.c,v 1.22 2001/01/13 14:34:06 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@ -62,3 +62,90 @@ Dbbe *sqliteDbbeOpen(
} }
return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg); return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg);
} }
/*
** Open a temporary file. The file should be deleted when closed.
**
** Note that we can't use the old Unix trick of opening the file
** and then immediately unlinking the file. That works great
** under Unix, but fails when we try to port to Windows.
*/
int sqliteDbbeOpenTempFile(Dbbe *pBe, FILE **ppFile){
char *zFile; /* Full name of the temporary file */
char zBuf[50]; /* Base name of the temporary file */
int i; /* Loop counter */
int limit; /* Prevent an infinite loop */
int rc = SQLITE_OK; /* Value returned by this function */
char *zDir; /* Directory to hold the file */
for(i=0; i<pBe->nTemp; i++){
if( pBe->apTemp[i]==0 ) break;
}
if( i>=pBe->nTemp ){
pBe->nTemp++;
pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) );
pBe->azTemp = sqliteRealloc(pBe->azTemp, pBe->nTemp*sizeof(char*) );
}
if( pBe->apTemp==0 ){
*ppFile = 0;
return SQLITE_NOMEM;
}
limit = 4;
zFile = 0;
zDir = pBe->zDir;
if( zDir==0 ){
zDir = "./";
}
do{
sqliteRandomName(zBuf, "/_temp_file_");
sqliteFree(zFile);
zFile = 0;
sqliteSetString(&zFile, zDir, zBuf, 0);
}while( access(zFile,0)==0 && limit-- >= 0 );
*ppFile = pBe->apTemp[i] = fopen(zFile, "w+");
if( pBe->apTemp[i]==0 ){
rc = SQLITE_ERROR;
sqliteFree(zFile);
pBe->azTemp[i] = 0;
}else{
pBe->azTemp[i] = zFile;
}
return rc;
}
/*
** Close a temporary file opened using sqliteGdbmOpenTempFile()
*/
void sqliteDbbeCloseTempFile(Dbbe *pBe, FILE *f){
int i;
for(i=0; i<pBe->nTemp; i++){
if( pBe->apTemp[i]==f ){
unlink(pBe->azTemp[i]);
sqliteFree(pBe->azTemp[i]);
pBe->apTemp[i] = 0;
pBe->azTemp[i] = 0;
break;
}
}
fclose(f);
}
/*
** Close all temporary files that happen to still be open.
** This routine is called when the database is being closed.
*/
void sqliteDbbeCloseAllTempFiles(Dbbe *pBe){
int i;
for(i=0; i<pBe->nTemp; i++){
if( pBe->apTemp[i]!=0 ){
unlink(pBe->azTemp[i]);
fclose(pBe->apTemp[i]);
sqliteFree(pBe->azTemp[i]);
pBe->apTemp[i] = 0;
pBe->azTemp[i] = 0;
break;
}
}
sqliteFree(pBe->azTemp);
sqliteFree(pBe->apTemp);
}

View File

@ -28,7 +28,7 @@
** This library was originally designed to support the following ** This library was originally designed to support the following
** backends: GDBM, NDBM, SDBM, Berkeley DB. ** backends: GDBM, NDBM, SDBM, Berkeley DB.
** **
** $Id: dbbe.h,v 1.8 2000/10/19 01:49:02 drh Exp $ ** $Id: dbbe.h,v 1.9 2001/01/13 14:34:06 drh Exp $
*/ */
#ifndef _SQLITE_DBBE_H_ #ifndef _SQLITE_DBBE_H_
#define _SQLITE_DBBE_H_ #define _SQLITE_DBBE_H_
@ -53,7 +53,7 @@
*/ */
typedef struct Dbbe Dbbe; typedef struct Dbbe Dbbe;
typedef struct DbbeCursor DbbeCursor; typedef struct DbbeCursor DbbeCursor;
typedef struct DbbeMethods DbbeMethods;
/* /*
** Open a complete database. ** Open a complete database.
@ -65,10 +65,13 @@ typedef struct DbbeCursor DbbeCursor;
Dbbe *sqliteDbbeOpen(const char *zName, int write, int create, char **pzErr); Dbbe *sqliteDbbeOpen(const char *zName, int write, int create, char **pzErr);
/* /*
** This is the structure returned by sqliteDbbeOpen(). It contains pointers ** Each of the various SQLite backends defines a set of methods for
** to all access routines for the database backend. ** accessing the database. Pointers to the methods are contained in
** an instance of the following structure. A pointer to a static instance
** of this structure is assigned to the Dbbe structure that sqlileDbbeOpen
** returns.
*/ */
struct Dbbe { struct DbbeMethods {
/* Close the whole database. */ /* Close the whole database. */
void (*Close)(Dbbe*); void (*Close)(Dbbe*);
@ -149,4 +152,22 @@ struct Dbbe {
void (*CloseTempFile)(Dbbe *, FILE *); void (*CloseTempFile)(Dbbe *, FILE *);
}; };
/*
** This is the structure returned by sqliteDbbeOpen(). It contains
** information common to all the different backend drivers.
**
** The information in this structure (with the exception the method
** pointers in the Dbbe.x field) is intended to be visible to
** the backend drivers only. Users should not access or modify
** this structure in any way other than the read the method pointers
** in Dbbe.x.
*/
struct Dbbe {
struct DbbeMethods *x; /* Backend-specific methods for database access */
char *zDir; /* The directory containing the database file(s) */
int nTemp; /* Number of temporary files created */
FILE **apTemp; /* Space to hold temporary file pointers */
char **azTemp; /* Names of the temporary files */
};
#endif /* defined(_SQLITE_DBBE_H_) */ #endif /* defined(_SQLITE_DBBE_H_) */

View File

@ -30,7 +30,7 @@
** relatively simple to convert to a different database such ** relatively simple to convert to a different database such
** as NDBM, SDBM, or BerkeleyDB. ** as NDBM, SDBM, or BerkeleyDB.
** **
** $Id: dbbegdbm.c,v 1.1 2000/10/19 01:49:02 drh Exp $ ** $Id: dbbegdbm.c,v 1.2 2001/01/13 14:34:06 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <gdbm.h> #include <gdbm.h>
@ -57,20 +57,6 @@ struct BeFile {
BeFile *pNext, *pPrev; /* Next and previous on list of open files */ BeFile *pNext, *pPrev; /* Next and previous on list of open files */
}; };
/*
** The following structure holds the current state of the RC4 algorithm.
** We use RC4 as a random number generator. Each call to RC4 gives
** a random 8-bit number.
**
** Nothing in this file or anywhere else in SQLite does any kind of
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
** number generator) not as an encryption device.
*/
struct rc4 {
int i, j;
int s[256];
};
/* /*
** The following structure contains all information used by GDBM ** The following structure contains all information used by GDBM
** database driver. This is a subclass of the Dbbe structure. ** database driver. This is a subclass of the Dbbe structure.
@ -78,13 +64,8 @@ struct rc4 {
typedef struct Dbbex Dbbex; typedef struct Dbbex Dbbex;
struct Dbbex { struct Dbbex {
Dbbe dbbe; /* The base class */ Dbbe dbbe; /* The base class */
char *zDir; /* The directory containing the database */
int write; /* True for write permission */ int write; /* True for write permission */
BeFile *pOpen; /* List of open files */ BeFile *pOpen; /* List of open files */
int nTemp; /* Number of temporary files created */
FILE **apTemp; /* Space to hold temporary file pointers */
char **azTemp; /* Names of the temporary files */
struct rc4 rc4; /* The random number generator */
}; };
/* /*
@ -105,41 +86,12 @@ struct DbbeCursor {
}; };
/* /*
** Initialize the RC4 PRNG. "seed" is a pointer to some random **
** data used to initialize the PRNG.
*/ */
static void rc4init(struct rc4 *p, char *seed, int seedlen){ struct DbbeList {
int i; FILE *pOut;
char k[256]; Dbbe *pDbbe;
p->j = 0; };
p->i = 0;
for(i=0; i<256; i++){
p->s[i] = i;
k[i] = seed[i%seedlen];
}
for(i=0; i<256; i++){
int t;
p->j = (p->j + p->s[i] + k[i]) & 0xff;
t = p->s[p->j];
p->s[p->j] = p->s[i];
p->s[i] = t;
}
}
/*
** Get a single 8-bit random value from the RC4 PRNG.
*/
static int rc4byte(struct rc4 *p){
int t;
p->i = (p->i + 1) & 0xff;
p->j = (p->j + p->s[p->i]) & 0xff;
t = p->s[p->i];
p->s[p->i] = p->s[p->j];
p->s[p->j] = t;
t = p->s[p->i] + p->s[p->j];
return t & 0xff;
}
/* /*
** The "mkdir()" function only takes one argument under Windows. ** The "mkdir()" function only takes one argument under Windows.
*/ */
@ -165,18 +117,7 @@ static void sqliteGdbmClose(Dbbe *pDbbe){
memset(pFile, 0, sizeof(*pFile)); memset(pFile, 0, sizeof(*pFile));
sqliteFree(pFile); sqliteFree(pFile);
} }
for(i=0; i<pBe->nTemp; i++){ sqliteDbbeCloseAllTempFiles(pDbbe);
if( pBe->apTemp[i]!=0 ){
unlink(pBe->azTemp[i]);
fclose(pBe->apTemp[i]);
sqliteFree(pBe->azTemp[i]);
pBe->apTemp[i] = 0;
pBe->azTemp[i] = 0;
break;
}
}
sqliteFree(pBe->azTemp);
sqliteFree(pBe->apTemp);
memset(pBe, 0, sizeof(*pBe)); memset(pBe, 0, sizeof(*pBe));
sqliteFree(pBe); sqliteFree(pBe);
} }
@ -190,9 +131,9 @@ static void sqliteGdbmClose(Dbbe *pDbbe){
static char *sqliteFileOfTable(Dbbex *pBe, const char *zTable){ static char *sqliteFileOfTable(Dbbex *pBe, const char *zTable){
char *zFile = 0; char *zFile = 0;
int i; int i;
sqliteSetString(&zFile, pBe->zDir, "/", zTable, ".tbl", 0); sqliteSetString(&zFile, pBe->dbbe.zDir, "/", zTable, ".tbl", 0);
if( zFile==0 ) return 0; if( zFile==0 ) return 0;
for(i=strlen(pBe->zDir)+1; zFile[i]; i++){ for(i=strlen(pBe->dbbe.zDir)+1; zFile[i]; i++){
int c = zFile[i]; int c = zFile[i];
if( isupper(c) ){ if( isupper(c) ){
zFile[i] = tolower(c); zFile[i] = tolower(c);
@ -203,27 +144,6 @@ static char *sqliteFileOfTable(Dbbex *pBe, const char *zTable){
return zFile; return zFile;
} }
/*
** Generate a random filename with the given prefix. The new filename
** is written into zBuf[]. The calling function must insure that
** zBuf[] is big enough to hold the prefix plus 20 or so extra
** characters.
**
** Very random names are chosen so that the chance of a
** collision with an existing filename is very very small.
*/
static void randomName(struct rc4 *pRc4, char *zBuf, char *zPrefix){
int i, j;
static const char zRandomChars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
strcpy(zBuf, zPrefix);
j = strlen(zBuf);
for(i=0; i<15; i++){
int c = rc4byte(pRc4) % (sizeof(zRandomChars) - 1);
zBuf[j++] = zRandomChars[c];
}
zBuf[j] = 0;
}
/* /*
** Open a new table cursor. Write a pointer to the corresponding ** Open a new table cursor. Write a pointer to the corresponding
** DbbeCursor structure into *ppCursr. Return an integer success ** DbbeCursor structure into *ppCursr. Return an integer success
@ -295,13 +215,11 @@ static int sqliteGdbmOpenCursor(
} }
}else{ }else{
int limit; int limit;
struct rc4 *pRc4;
char zRandom[50]; char zRandom[50];
pRc4 = &pBe->rc4;
zFile = 0; zFile = 0;
limit = 5; limit = 5;
do { do {
randomName(&pBe->rc4, zRandom, "_temp_table_"); sqliteRandomName(zRandom, "_temp_table_");
sqliteFree(zFile); sqliteFree(zFile);
zFile = sqliteFileOfTable(pBe, zRandom); zFile = sqliteFileOfTable(pBe, zRandom);
pFile->dbf = gdbm_open(zFile, 0, rw_mask, mode, 0); pFile->dbf = gdbm_open(zFile, 0, rw_mask, mode, 0);
@ -577,15 +495,10 @@ static int sqliteGdbmNew(DbbeCursor *pCursr){
datum key; datum key;
int go = 1; int go = 1;
int i; int i;
struct rc4 *pRc4;
if( pCursr->pFile==0 || pCursr->pFile->dbf==0 ) return 1; if( pCursr->pFile==0 || pCursr->pFile->dbf==0 ) return 1;
pRc4 = &pCursr->pBe->rc4;
while( go ){ while( go ){
iKey = 0; iKey = sqliteRandomInteger();
for(i=0; i<4; i++){
iKey = (iKey<<8) + rc4byte(pRc4);
}
if( iKey==0 ) continue; if( iKey==0 ) continue;
key.dptr = (char*)&iKey; key.dptr = (char*)&iKey;
key.dsize = 4; key.dsize = 4;
@ -631,68 +544,31 @@ static int sqliteGdbmDelete(DbbeCursor *pCursr, int nKey, char *pKey){
} }
/* /*
** Open a temporary file. The file should be deleted when closed. ** This variable contains pointers to all of the access methods
** ** used to implement the GDBM backend.
** Note that we can't use the old Unix trick of opening the file
** and then immediately unlinking the file. That works great
** under Unix, but fails when we try to port to Windows.
*/ */
static int sqliteGdbmOpenTempFile(Dbbe *pDbbe, FILE **ppFile){ static struct DbbeMethods gdbmMethods = {
char *zFile; /* Full name of the temporary file */ /* n Close */ sqliteGdbmClose,
char zBuf[50]; /* Base name of the temporary file */ /* OpenCursor */ sqliteGdbmOpenCursor,
int i; /* Loop counter */ /* DropTable */ sqliteGdbmDropTable,
int limit; /* Prevent an infinite loop */ /* ReorganizeTable */ sqliteGdbmReorganizeTable,
int rc = SQLITE_OK; /* Value returned by this function */ /* CloseCursor */ sqliteGdbmCloseCursor,
Dbbex *pBe = (Dbbex*)pDbbe; /* Fetch */ sqliteGdbmFetch,
/* Test */ sqliteGdbmTest,
for(i=0; i<pBe->nTemp; i++){ /* CopyKey */ sqliteGdbmCopyKey,
if( pBe->apTemp[i]==0 ) break; /* CopyData */ sqliteGdbmCopyData,
} /* ReadKey */ sqliteGdbmReadKey,
if( i>=pBe->nTemp ){ /* ReadData */ sqliteGdbmReadData,
pBe->nTemp++; /* KeyLength */ sqliteGdbmKeyLength,
pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) ); /* DataLength */ sqliteGdbmDataLength,
pBe->azTemp = sqliteRealloc(pBe->azTemp, pBe->nTemp*sizeof(char*) ); /* NextKey */ sqliteGdbmNextKey,
} /* Rewind */ sqliteGdbmRewind,
if( pBe->apTemp==0 ){ /* New */ sqliteGdbmNew,
*ppFile = 0; /* Put */ sqliteGdbmPut,
return SQLITE_NOMEM; /* Delete */ sqliteGdbmDelete,
} /* OpenTempFile */ sqliteDbbeOpenTempFile,
limit = 4; /* CloseTempFile */ sqliteDbbeCloseTempFile
zFile = 0; };
do{
randomName(&pBe->rc4, zBuf, "/_temp_file_");
sqliteFree(zFile);
zFile = 0;
sqliteSetString(&zFile, pBe->zDir, zBuf, 0);
}while( access(zFile,0)==0 && limit-- >= 0 );
*ppFile = pBe->apTemp[i] = fopen(zFile, "w+");
if( pBe->apTemp[i]==0 ){
rc = SQLITE_ERROR;
sqliteFree(zFile);
pBe->azTemp[i] = 0;
}else{
pBe->azTemp[i] = zFile;
}
return rc;
}
/*
** Close a temporary file opened using sqliteGdbmOpenTempFile()
*/
static void sqliteGdbmCloseTempFile(Dbbe *pDbbe, FILE *f){
int i;
Dbbex *pBe = (Dbbex*)pDbbe;
for(i=0; i<pBe->nTemp; i++){
if( pBe->apTemp[i]==f ){
unlink(pBe->azTemp[i]);
sqliteFree(pBe->azTemp[i]);
pBe->apTemp[i] = 0;
pBe->azTemp[i] = 0;
break;
}
}
fclose(f);
}
/* /*
@ -746,31 +622,10 @@ Dbbe *sqliteGdbmOpen(
sqliteSetString(pzErrMsg, "out of memory", 0); sqliteSetString(pzErrMsg, "out of memory", 0);
return 0; return 0;
} }
pNew->dbbe.Close = sqliteGdbmClose; pNew->dbbe.x = &gdbmMethods;
pNew->dbbe.OpenCursor = sqliteGdbmOpenCursor; pNew->dbbe.zDir = (char*)&pNew[1];
pNew->dbbe.DropTable = sqliteGdbmDropTable; strcpy(pNew->dbbe.zDir, zName);
pNew->dbbe.ReorganizeTable = sqliteGdbmReorganizeTable;
pNew->dbbe.CloseCursor = sqliteGdbmCloseCursor;
pNew->dbbe.Fetch = sqliteGdbmFetch;
pNew->dbbe.Test = sqliteGdbmTest;
pNew->dbbe.CopyKey = sqliteGdbmCopyKey;
pNew->dbbe.CopyData = sqliteGdbmCopyData;
pNew->dbbe.ReadKey = sqliteGdbmReadKey;
pNew->dbbe.ReadData = sqliteGdbmReadData;
pNew->dbbe.KeyLength = sqliteGdbmKeyLength;
pNew->dbbe.DataLength = sqliteGdbmDataLength;
pNew->dbbe.NextKey = sqliteGdbmNextKey;
pNew->dbbe.Rewind = sqliteGdbmRewind;
pNew->dbbe.New = sqliteGdbmNew;
pNew->dbbe.Put = sqliteGdbmPut;
pNew->dbbe.Delete = sqliteGdbmDelete;
pNew->dbbe.OpenTempFile = sqliteGdbmOpenTempFile;
pNew->dbbe.CloseTempFile = sqliteGdbmCloseTempFile;
pNew->zDir = (char*)&pNew[1];
strcpy(pNew->zDir, zName);
pNew->write = writeFlag; pNew->write = writeFlag;
pNew->pOpen = 0; pNew->pOpen = 0;
time(&statbuf.st_ctime);
rc4init(&pNew->rc4, (char*)&statbuf, sizeof(statbuf));
return &pNew->dbbe; return &pNew->dbbe;
} }

View File

@ -28,7 +28,7 @@
** **
** This file uses an in-memory hash table as the database backend. ** This file uses an in-memory hash table as the database backend.
** **
** $Id: dbbemem.c,v 1.5 2000/12/10 18:23:50 drh Exp $ ** $Id: dbbemem.c,v 1.6 2001/01/13 14:34:06 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <sys/stat.h> #include <sys/stat.h>
@ -342,20 +342,6 @@ struct MTable {
Array data; /* The data in this stable */ Array data; /* The data in this stable */
}; };
/*
** The following structure holds the current state of the RC4 algorithm.
** We use RC4 as a random number generator. Each call to RC4 gives
** a random 8-bit number.
**
** Nothing in this file or anywhere else in SQLite does any kind of
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
** number generator) not as an encryption device.
*/
struct rc4 {
int i, j;
int s[256];
};
/* /*
** The following structure contains all information used by GDBM ** The following structure contains all information used by GDBM
** database driver. This is a subclass of the Dbbe structure. ** database driver. This is a subclass of the Dbbe structure.
@ -364,10 +350,6 @@ typedef struct Dbbex Dbbex;
struct Dbbex { struct Dbbex {
Dbbe dbbe; /* The base class */ Dbbe dbbe; /* The base class */
Array tables; /* All tables of the database */ Array tables; /* All tables of the database */
int nTemp; /* Number of temporary files created */
FILE **apTemp; /* Space to hold temporary file pointers */
char **azTemp; /* Names of the temporary files */
struct rc4 rc4; /* The random number generator */
}; };
/* /*
@ -385,42 +367,6 @@ struct DbbeCursor {
int needRewind; /* Next key should be the first */ int needRewind; /* Next key should be the first */
}; };
/*
** Initialize the RC4 PRNG. "seed" is a pointer to some random
** data used to initialize the PRNG.
*/
static void rc4init(struct rc4 *p, char *seed, int seedlen){
int i;
char k[256];
p->j = 0;
p->i = 0;
for(i=0; i<256; i++){
p->s[i] = i;
k[i] = seed[i%seedlen];
}
for(i=0; i<256; i++){
int t;
p->j = (p->j + p->s[i] + k[i]) & 0xff;
t = p->s[p->j];
p->s[p->j] = p->s[i];
p->s[i] = t;
}
}
/*
** Get a single 8-bit random value from the RC4 PRNG.
*/
static int rc4byte(struct rc4 *p){
int t;
p->i = (p->i + 1) & 0xff;
p->j = (p->j + p->s[p->i]) & 0xff;
t = p->s[p->i];
p->s[p->i] = p->s[p->j];
p->s[p->j] = t;
t = p->s[p->i] + p->s[p->j];
return t & 0xff;
}
/* /*
** Forward declaration ** Forward declaration
*/ */
@ -453,43 +399,11 @@ static void sqliteMemClose(Dbbe *pDbbe){
deleteMTable(pTble); deleteMTable(pTble);
} }
ArrayClear(&pBe->tables); ArrayClear(&pBe->tables);
for(i=0; i<pBe->nTemp; i++){ sqliteDbbeCloseAllTempFiles(pDbbe);
if( pBe->apTemp[i]!=0 ){
unlink(pBe->azTemp[i]);
fclose(pBe->apTemp[i]);
sqliteFree(pBe->azTemp[i]);
pBe->apTemp[i] = 0;
pBe->azTemp[i] = 0;
break;
}
}
sqliteFree(pBe->azTemp);
sqliteFree(pBe->apTemp);
memset(pBe, 0, sizeof(*pBe)); memset(pBe, 0, sizeof(*pBe));
sqliteFree(pBe); sqliteFree(pBe);
} }
/*
** Generate a random filename with the given prefix. The new filename
** is written into zBuf[]. The calling function must insure that
** zBuf[] is big enough to hold the prefix plus 20 or so extra
** characters.
**
** Very random names are chosen so that the chance of a
** collision with an existing filename is very very small.
*/
static void randomName(struct rc4 *pRc4, char *zBuf, char *zPrefix){
int i, j;
static const char zRandomChars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
strcpy(zBuf, zPrefix);
j = strlen(zBuf);
for(i=0; i<15; i++){
int c = rc4byte(pRc4) % (sizeof(zRandomChars) - 1);
zBuf[j++] = zRandomChars[c];
}
zBuf[j] = 0;
}
/* /*
** Translate the name of an SQL table (or index) into its ** Translate the name of an SQL table (or index) into its
** canonical name. ** canonical name.
@ -752,14 +666,9 @@ static int sqliteMemNew(DbbeCursor *pCursr){
Datum key; Datum key;
int go = 1; int go = 1;
int i; int i;
struct rc4 *pRc4;
pRc4 = &pCursr->pBe->rc4;
while( go ){ while( go ){
iKey = 0; iKey = sqliteRandomInteger();
for(i=0; i<4; i++){
iKey = (iKey<<8) + rc4byte(pRc4);
}
if( iKey==0 ) continue; if( iKey==0 ) continue;
key.p = (char*)&iKey; key.p = (char*)&iKey;
key.n = 4; key.n = 4;
@ -804,69 +713,31 @@ static int sqliteMemDelete(DbbeCursor *pCursr, int nKey, char *pKey){
} }
/* /*
** Open a temporary file. The file should be deleted when closed. ** This variable contains pointers to all of the access methods
** ** used to implement the MEMORY backend.
** Note that we can't use the old Unix trick of opening the file
** and then immediately unlinking the file. That works great
** under Unix, but fails when we try to port to Windows.
*/ */
static int sqliteMemOpenTempFile(Dbbe *pDbbe, FILE **ppTble){ static struct DbbeMethods memoryMethods = {
char *zName; /* Full name of the temporary file */ /* n Close */ sqliteMemClose,
char zBuf[50]; /* Base name of the temporary file */ /* OpenCursor */ sqliteMemOpenCursor,
int i; /* Loop counter */ /* DropTable */ sqliteMemDropTable,
int limit; /* Prevent an infinite loop */ /* ReorganizeTable */ sqliteMemReorganizeTable,
int rc = SQLITE_OK; /* Value returned by this function */ /* CloseCursor */ sqliteMemCloseCursor,
Dbbex *pBe = (Dbbex*)pDbbe; /* Fetch */ sqliteMemFetch,
/* Test */ sqliteMemTest,
for(i=0; i<pBe->nTemp; i++){ /* CopyKey */ sqliteMemCopyKey,
if( pBe->apTemp[i]==0 ) break; /* CopyData */ sqliteMemCopyData,
} /* ReadKey */ sqliteMemReadKey,
if( i>=pBe->nTemp ){ /* ReadData */ sqliteMemReadData,
pBe->nTemp++; /* KeyLength */ sqliteMemKeyLength,
pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) ); /* DataLength */ sqliteMemDataLength,
pBe->azTemp = sqliteRealloc(pBe->azTemp, pBe->nTemp*sizeof(char*) ); /* NextKey */ sqliteMemNextKey,
} /* Rewind */ sqliteMemRewind,
if( pBe->apTemp==0 ){ /* New */ sqliteMemNew,
*ppTble = 0; /* Put */ sqliteMemPut,
return SQLITE_NOMEM; /* Delete */ sqliteMemDelete,
} /* OpenTempFile */ sqliteDbbeOpenTempFile,
limit = 4; /* CloseTempFile */ sqliteDbbeCloseTempFile
zName = 0; };
do{
randomName(&pBe->rc4, zBuf, "/tmp/_temp_file_");
sqliteFree(zName);
zName = 0;
sqliteSetString(&zName, zBuf, 0);
}while( access(zName,0)==0 && limit-- >= 0 );
*ppTble = pBe->apTemp[i] = fopen(zName, "w+");
if( pBe->apTemp[i]==0 ){
rc = SQLITE_ERROR;
sqliteFree(zName);
pBe->azTemp[i] = 0;
}else{
pBe->azTemp[i] = zName;
}
return rc;
}
/*
** Close a temporary file opened using sqliteMemOpenTempFile()
*/
static void sqliteMemCloseTempFile(Dbbe *pDbbe, FILE *f){
int i;
Dbbex *pBe = (Dbbex*)pDbbe;
for(i=0; i<pBe->nTemp; i++){
if( pBe->apTemp[i]==f ){
unlink(pBe->azTemp[i]);
sqliteFree(pBe->azTemp[i]);
pBe->apTemp[i] = 0;
pBe->azTemp[i] = 0;
break;
}
}
fclose(f);
}
/* /*
** This routine opens a new database. For the GDBM driver ** This routine opens a new database. For the GDBM driver
@ -884,7 +755,6 @@ Dbbe *sqliteMemOpen(
char **pzErrMsg /* Write error messages (if any) here */ char **pzErrMsg /* Write error messages (if any) here */
){ ){
Dbbex *pNew; Dbbex *pNew;
long now;
pNew = sqliteMalloc( sizeof(*pNew) ); pNew = sqliteMalloc( sizeof(*pNew) );
if( pNew==0 ){ if( pNew==0 ){
@ -892,27 +762,7 @@ Dbbe *sqliteMemOpen(
return 0; return 0;
} }
ArrayInit(&pNew->tables); ArrayInit(&pNew->tables);
pNew->dbbe.Close = sqliteMemClose; pNew->dbbe.x = &memoryMethods;
pNew->dbbe.OpenCursor = sqliteMemOpenCursor; pNew->dbbe.zDir = 0;
pNew->dbbe.DropTable = sqliteMemDropTable;
pNew->dbbe.ReorganizeTable = sqliteMemReorganizeTable;
pNew->dbbe.CloseCursor = sqliteMemCloseCursor;
pNew->dbbe.Fetch = sqliteMemFetch;
pNew->dbbe.Test = sqliteMemTest;
pNew->dbbe.CopyKey = sqliteMemCopyKey;
pNew->dbbe.CopyData = sqliteMemCopyData;
pNew->dbbe.ReadKey = sqliteMemReadKey;
pNew->dbbe.ReadData = sqliteMemReadData;
pNew->dbbe.KeyLength = sqliteMemKeyLength;
pNew->dbbe.DataLength = sqliteMemDataLength;
pNew->dbbe.NextKey = sqliteMemNextKey;
pNew->dbbe.Rewind = sqliteMemRewind;
pNew->dbbe.New = sqliteMemNew;
pNew->dbbe.Put = sqliteMemPut;
pNew->dbbe.Delete = sqliteMemDelete;
pNew->dbbe.OpenTempFile = sqliteMemOpenTempFile;
pNew->dbbe.CloseTempFile = sqliteMemCloseTempFile;
time(&now);
rc4init(&pNew->rc4, (char*)&now, sizeof(now));
return &pNew->dbbe; return &pNew->dbbe;
} }

View File

@ -26,7 +26,7 @@
** other files are for internal use by SQLite and should not be ** other files are for internal use by SQLite and should not be
** accessed by users of the library. ** accessed by users of the library.
** **
** $Id: main.c,v 1.22 2000/12/10 18:23:50 drh Exp $ ** $Id: main.c,v 1.23 2001/01/13 14:34:06 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@ -239,7 +239,7 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
*/ */
void sqlite_close(sqlite *db){ void sqlite_close(sqlite *db){
int i; int i;
db->pBe->Close(db->pBe); db->pBe->x->Close(db->pBe);
for(i=0; i<N_HASH; i++){ for(i=0; i<N_HASH; i++){
Table *pNext, *pList = db->apTblHash[i]; Table *pNext, *pList = db->apTblHash[i];
db->apTblHash[i] = 0; db->apTblHash[i] = 0;

127
src/random.c Normal file
View File

@ -0,0 +1,127 @@
/*
** Copyright (c) 2000 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA 02111-1307, USA.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains code to implement a pseudo-random number
** generator (PRNG) for SQLite.
**
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
** $Id: random.c,v 1.1 2001/01/13 14:34:07 drh Exp $
*/
#include "sqliteInt.h"
/*
** Get a single 8-bit random value from the RC4 PRNG.
*/
int sqliteRandomByte(void){
int t;
/*
** The following structure holds the current state of the RC4 algorithm.
** We use RC4 as a random number generator. Each call to RC4 gives
** a random 8-bit number.
**
** Nothing in this file or anywhere else in SQLite does any kind of
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
** number generator) not as an encryption device.
*/
static struct {
int isInit;
int i, j;
int s[256];
} prng_state;
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
** trying to do secure encryption or anything like that...
*/
if( !prng_state.isInit ){
int i;
static char seed[] = " sqlite random seed";
char k[256];
time((time_t*)seed);
prng_state.j = 0;
prng_state.i = 0;
for(i=0; i<256; i++){
prng_state.s[i] = i;
k[i] = seed[i%sizeof(seed)];
}
for(i=0; i<256; i++){
int t;
prng_state.j = (prng_state.j + prng_state.s[i] + k[i]) & 0xff;
t = prng_state.s[prng_state.j];
prng_state.s[prng_state.j] = prng_state.s[i];
prng_state.s[i] = t;
}
prng_state.isInit = 1;
}
/* Generate and return single random byte
*/
prng_state.i = (prng_state.i + 1) & 0xff;
prng_state.j = (prng_state.j + prng_state.s[prng_state.i]) & 0xff;
t = prng_state.s[prng_state.i];
prng_state.s[prng_state.i] = prng_state.s[prng_state.j];
prng_state.s[prng_state.j] = t;
t = prng_state.s[prng_state.i] + prng_state.s[prng_state.j];
return t & 0xff;
}
/*
** Return a random 32-bit integer. The integer is generated by making
** 4 calls to sqliteRandomByte().
*/
int sqliteRandomInteger(void){
int r;
int i;
r = sqliteRandomByte();
for(i=1; i<4; i++){
r = (r<<8) + sqliteRandomByte();
}
return r;
}
/*
** Generate a random filename with the given prefix. The new filename
** is written into zBuf[]. The calling function must insure that
** zBuf[] is big enough to hold the prefix plus 20 or so extra
** characters.
**
** Very random names are chosen so that the chance of a
** collision with an existing filename is very very small.
*/
void sqliteRandomName(char *zBuf, char *zPrefix){
int i, j;
static const char zRandomChars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
strcpy(zBuf, zPrefix);
j = strlen(zBuf);
for(i=0; i<15; i++){
int c = sqliteRandomByte() % (sizeof(zRandomChars) - 1);
zBuf[j++] = zRandomChars[c];
}
zBuf[j] = 0;
}

View File

@ -23,7 +23,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.33 2000/12/10 18:23:51 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.34 2001/01/13 14:34:07 drh Exp $
*/ */
#include "sqlite.h" #include "sqlite.h"
#include "dbbe.h" #include "dbbe.h"
@ -419,3 +419,8 @@ void sqliteExprResolveInSelect(Parse*, Expr*);
int sqliteExprAnalyzeAggregates(Parse*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*);
void sqliteParseInfoReset(Parse*); void sqliteParseInfoReset(Parse*);
Vdbe *sqliteGetVdbe(Parse*); Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte(void);
int sqliteRandomInteger(void);
void sqliteRandomName(char*,char*);
int sqliteDbbeOpenTempFile(Dbbe*, FILE**);
void sqliteDbbeCloseTempFile(Dbbe*, FILE*);

View File

@ -41,7 +41,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.49 2000/12/10 18:35:20 drh Exp $ ** $Id: vdbe.c,v 1.50 2001/01/13 14:34:07 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <unistd.h> #include <unistd.h>
@ -696,7 +696,7 @@ static void Cleanup(Vdbe *p){
p->azColName = 0; p->azColName = 0;
for(i=0; i<p->nCursor; i++){ for(i=0; i<p->nCursor; i++){
if( p->aCsr[i].pCursor ){ if( p->aCsr[i].pCursor ){
p->pBe->CloseCursor(p->aCsr[i].pCursor); p->pBe->x->CloseCursor(p->aCsr[i].pCursor);
p->aCsr[i].pCursor = 0; p->aCsr[i].pCursor = 0;
} }
} }
@ -713,7 +713,7 @@ static void Cleanup(Vdbe *p){
p->nMem = 0; p->nMem = 0;
for(i=0; i<p->nList; i++){ for(i=0; i<p->nList; i++){
if( p->apList[i] ){ if( p->apList[i] ){
p->pBe->CloseTempFile(p->pBe, p->apList[i]); p->pBe->x->CloseTempFile(p->pBe, p->apList[i]);
p->apList[i] = 0; p->apList[i] = 0;
} }
} }
@ -953,6 +953,7 @@ int sqliteVdbeExec(
Op *pOp; /* Current operation */ Op *pOp; /* Current operation */
int rc; /* Value to return */ int rc; /* Value to return */
Dbbe *pBe = p->pBe; /* The backend driver */ Dbbe *pBe = p->pBe; /* The backend driver */
DbbeMethods *pBex = pBe->x; /* The backend driver methods */
sqlite *db = p->db; /* The database */ sqlite *db = p->db; /* The database */
char **zStack; char **zStack;
Stack *aStack; Stack *aStack;
@ -1809,10 +1810,10 @@ int sqliteVdbeExec(
for(j=p->nCursor; j<=i; j++) p->aCsr[j].pCursor = 0; for(j=p->nCursor; j<=i; j++) p->aCsr[j].pCursor = 0;
p->nCursor = i+1; p->nCursor = i+1;
}else if( p->aCsr[i].pCursor ){ }else if( p->aCsr[i].pCursor ){
pBe->CloseCursor(p->aCsr[i].pCursor); pBex->CloseCursor(p->aCsr[i].pCursor);
} }
do { do {
rc = pBe->OpenCursor(pBe,pOp->p3,pOp->p2,&p->aCsr[i].pCursor); rc = pBex->OpenCursor(pBe,pOp->p3,pOp->p2,&p->aCsr[i].pCursor);
switch( rc ){ switch( rc ){
case SQLITE_BUSY: { case SQLITE_BUSY: {
if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){ if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){
@ -1853,7 +1854,7 @@ int sqliteVdbeExec(
case OP_Close: { case OP_Close: {
int i = pOp->p1; int i = pOp->p1;
if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){ if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){
pBe->CloseCursor(p->aCsr[i].pCursor); pBex->CloseCursor(p->aCsr[i].pCursor);
p->aCsr[i].pCursor = 0; p->aCsr[i].pCursor = 0;
} }
break; break;
@ -1871,11 +1872,11 @@ int sqliteVdbeExec(
VERIFY( if( tos<0 ) goto not_enough_stack; ) VERIFY( if( tos<0 ) goto not_enough_stack; )
if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){ if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){
if( aStack[tos].flags & STK_Int ){ if( aStack[tos].flags & STK_Int ){
pBe->Fetch(p->aCsr[i].pCursor, sizeof(int), pBex->Fetch(p->aCsr[i].pCursor, sizeof(int),
(char*)&aStack[tos].i); (char*)&aStack[tos].i);
}else{ }else{
if( Stringify(p, tos) ) goto no_mem; if( Stringify(p, tos) ) goto no_mem;
pBe->Fetch(p->aCsr[i].pCursor, aStack[tos].n, pBex->Fetch(p->aCsr[i].pCursor, aStack[tos].n,
zStack[tos]); zStack[tos]);
} }
p->nFetch++; p->nFetch++;
@ -1937,11 +1938,11 @@ int sqliteVdbeExec(
VERIFY( if( tos<0 ) goto not_enough_stack; ) VERIFY( if( tos<0 ) goto not_enough_stack; )
if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor ){ if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor ){
if( aStack[tos].flags & STK_Int ){ if( aStack[tos].flags & STK_Int ){
alreadyExists = pBe->Test(p->aCsr[i].pCursor, sizeof(int), alreadyExists = pBex->Test(p->aCsr[i].pCursor, sizeof(int),
(char*)&aStack[tos].i); (char*)&aStack[tos].i);
}else{ }else{
if( Stringify(p, tos) ) goto no_mem; if( Stringify(p, tos) ) goto no_mem;
alreadyExists = pBe->Test(p->aCsr[i].pCursor,aStack[tos].n, alreadyExists = pBex->Test(p->aCsr[i].pCursor,aStack[tos].n,
zStack[tos]); zStack[tos]);
} }
} }
@ -1967,7 +1968,7 @@ int sqliteVdbeExec(
if( VERIFY( i<0 || i>=p->nCursor || ) p->aCsr[i].pCursor==0 ){ if( VERIFY( i<0 || i>=p->nCursor || ) p->aCsr[i].pCursor==0 ){
v = 0; v = 0;
}else{ }else{
v = pBe->New(p->aCsr[i].pCursor); v = pBex->New(p->aCsr[i].pCursor);
} }
VERIFY( NeedStack(p, p->tos+1); ) VERIFY( NeedStack(p, p->tos+1); )
p->tos++; p->tos++;
@ -2000,7 +2001,7 @@ int sqliteVdbeExec(
nKey = sizeof(int); nKey = sizeof(int);
zKey = (char*)&aStack[nos].i; zKey = (char*)&aStack[nos].i;
} }
pBe->Put(p->aCsr[i].pCursor, nKey, zKey, pBex->Put(p->aCsr[i].pCursor, nKey, zKey,
aStack[tos].n, zStack[tos]); aStack[tos].n, zStack[tos]);
} }
POPSTACK; POPSTACK;
@ -2028,7 +2029,7 @@ int sqliteVdbeExec(
nKey = aStack[tos].n; nKey = aStack[tos].n;
zKey = zStack[tos]; zKey = zStack[tos];
} }
pBe->Delete(p->aCsr[i].pCursor, nKey, zKey); pBex->Delete(p->aCsr[i].pCursor, nKey, zKey);
} }
POPSTACK; POPSTACK;
break; break;
@ -2082,29 +2083,29 @@ int sqliteVdbeExec(
VERIFY( if( NeedStack(p, tos) ) goto no_mem; ) VERIFY( if( NeedStack(p, tos) ) goto no_mem; )
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
if( p->aCsr[i].keyAsData ){ if( p->aCsr[i].keyAsData ){
amt = pBe->KeyLength(pCrsr); amt = pBex->KeyLength(pCrsr);
if( amt<=sizeof(int)*(p2+1) ){ if( amt<=sizeof(int)*(p2+1) ){
aStack[tos].flags = STK_Null; aStack[tos].flags = STK_Null;
break; break;
} }
pAddr = (int*)pBe->ReadKey(pCrsr, sizeof(int)*p2); pAddr = (int*)pBex->ReadKey(pCrsr, sizeof(int)*p2);
if( *pAddr==0 ){ if( *pAddr==0 ){
aStack[tos].flags = STK_Null; aStack[tos].flags = STK_Null;
break; break;
} }
z = pBe->ReadKey(pCrsr, *pAddr); z = pBex->ReadKey(pCrsr, *pAddr);
}else{ }else{
amt = pBe->DataLength(pCrsr); amt = pBex->DataLength(pCrsr);
if( amt<=sizeof(int)*(p2+1) ){ if( amt<=sizeof(int)*(p2+1) ){
aStack[tos].flags = STK_Null; aStack[tos].flags = STK_Null;
break; break;
} }
pAddr = (int*)pBe->ReadData(pCrsr, sizeof(int)*p2); pAddr = (int*)pBex->ReadData(pCrsr, sizeof(int)*p2);
if( *pAddr==0 ){ if( *pAddr==0 ){
aStack[tos].flags = STK_Null; aStack[tos].flags = STK_Null;
break; break;
} }
z = pBe->ReadData(pCrsr, *pAddr); z = pBex->ReadData(pCrsr, *pAddr);
} }
zStack[tos] = z; zStack[tos] = z;
aStack[tos].n = strlen(z) + 1; aStack[tos].n = strlen(z) + 1;
@ -2127,11 +2128,11 @@ int sqliteVdbeExec(
VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
char *z = pBe->ReadKey(pCrsr, 0); char *z = pBex->ReadKey(pCrsr, 0);
if( p->aCsr[i].keyAsData ){ if( p->aCsr[i].keyAsData ){
zStack[tos] = z; zStack[tos] = z;
aStack[tos].flags = STK_Str; aStack[tos].flags = STK_Str;
aStack[tos].n = pBe->KeyLength(pCrsr); aStack[tos].n = pBex->KeyLength(pCrsr);
}else{ }else{
memcpy(&aStack[tos].i, z, sizeof(int)); memcpy(&aStack[tos].i, z, sizeof(int));
aStack[tos].flags = STK_Int; aStack[tos].flags = STK_Int;
@ -2148,7 +2149,7 @@ int sqliteVdbeExec(
case OP_Rewind: { case OP_Rewind: {
int i = pOp->p1; int i = pOp->p1;
if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){ if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){
pBe->Rewind(p->aCsr[i].pCursor); pBex->Rewind(p->aCsr[i].pCursor);
} }
break; break;
} }
@ -2161,7 +2162,7 @@ int sqliteVdbeExec(
case OP_Next: { case OP_Next: {
int i = pOp->p1; int i = pOp->p1;
if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){ if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){
if( pBe->NextKey(p->aCsr[i].pCursor)==0 ){ if( pBex->NextKey(p->aCsr[i].pCursor)==0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
}else{ }else{
p->nFetch++; p->nFetch++;
@ -2211,8 +2212,8 @@ int sqliteVdbeExec(
int *aIdx; int *aIdx;
int nIdx; int nIdx;
int j, k; int j, k;
nIdx = pBe->DataLength(pCrsr)/sizeof(int); nIdx = pBex->DataLength(pCrsr)/sizeof(int);
aIdx = (int*)pBe->ReadData(pCrsr, 0); aIdx = (int*)pBex->ReadData(pCrsr, 0);
if( nIdx>1 ){ if( nIdx>1 ){
k = *(aIdx++); k = *(aIdx++);
if( k>nIdx-1 ) k = nIdx-1; if( k>nIdx-1 ) k = nIdx-1;
@ -2257,10 +2258,10 @@ int sqliteVdbeExec(
Integerify(p, nos); Integerify(p, nos);
newVal = aStack[nos].i; newVal = aStack[nos].i;
if( Stringify(p, tos) ) goto no_mem; if( Stringify(p, tos) ) goto no_mem;
r = pBe->Fetch(pCrsr, aStack[tos].n, zStack[tos]); r = pBex->Fetch(pCrsr, aStack[tos].n, zStack[tos]);
if( r==0 ){ if( r==0 ){
/* Create a new record for this index */ /* Create a new record for this index */
pBe->Put(pCrsr, aStack[tos].n, zStack[tos], pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
sizeof(int), (char*)&newVal); sizeof(int), (char*)&newVal);
}else{ }else{
/* Extend the existing record */ /* Extend the existing record */
@ -2268,32 +2269,32 @@ int sqliteVdbeExec(
int *aIdx; int *aIdx;
int k; int k;
nIdx = pBe->DataLength(pCrsr)/sizeof(int); nIdx = pBex->DataLength(pCrsr)/sizeof(int);
if( nIdx==1 ){ if( nIdx==1 ){
aIdx = sqliteMalloc( sizeof(int)*4 ); aIdx = sqliteMalloc( sizeof(int)*4 );
if( aIdx==0 ) goto no_mem; if( aIdx==0 ) goto no_mem;
aIdx[0] = 2; aIdx[0] = 2;
pBe->CopyData(pCrsr, 0, sizeof(int), (char*)&aIdx[1]); pBex->CopyData(pCrsr, 0, sizeof(int), (char*)&aIdx[1]);
aIdx[2] = newVal; aIdx[2] = newVal;
pBe->Put(pCrsr, aStack[tos].n, zStack[tos], pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
sizeof(int)*4, (char*)aIdx); sizeof(int)*4, (char*)aIdx);
sqliteFree(aIdx); sqliteFree(aIdx);
}else{ }else{
aIdx = (int*)pBe->ReadData(pCrsr, 0); aIdx = (int*)pBex->ReadData(pCrsr, 0);
k = aIdx[0]; k = aIdx[0];
if( k<nIdx-1 ){ if( k<nIdx-1 ){
aIdx[k+1] = newVal; aIdx[k+1] = newVal;
aIdx[0]++; aIdx[0]++;
pBe->Put(pCrsr, aStack[tos].n, zStack[tos], pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
sizeof(int)*nIdx, (char*)aIdx); sizeof(int)*nIdx, (char*)aIdx);
}else{ }else{
nIdx *= 2; nIdx *= 2;
aIdx = sqliteMalloc( sizeof(int)*nIdx ); aIdx = sqliteMalloc( sizeof(int)*nIdx );
if( aIdx==0 ) goto no_mem; if( aIdx==0 ) goto no_mem;
pBe->CopyData(pCrsr, 0, sizeof(int)*(k+1), (char*)aIdx); pBex->CopyData(pCrsr, 0, sizeof(int)*(k+1), (char*)aIdx);
aIdx[k+1] = newVal; aIdx[k+1] = newVal;
aIdx[0]++; aIdx[0]++;
pBe->Put(pCrsr, aStack[tos].n, zStack[tos], pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
sizeof(int)*nIdx, (char*)aIdx); sizeof(int)*nIdx, (char*)aIdx);
sqliteFree(aIdx); sqliteFree(aIdx);
} }
@ -2333,12 +2334,12 @@ int sqliteVdbeExec(
Integerify(p, nos); Integerify(p, nos);
oldVal = aStack[nos].i; oldVal = aStack[nos].i;
if( Stringify(p, tos) ) goto no_mem; if( Stringify(p, tos) ) goto no_mem;
r = pBe->Fetch(pCrsr, aStack[tos].n, zStack[tos]); r = pBex->Fetch(pCrsr, aStack[tos].n, zStack[tos]);
if( r==0 ) break; if( r==0 ) break;
nIdx = pBe->DataLength(pCrsr)/sizeof(int); nIdx = pBex->DataLength(pCrsr)/sizeof(int);
aIdx = (int*)pBe->ReadData(pCrsr, 0); aIdx = (int*)pBex->ReadData(pCrsr, 0);
if( (nIdx==1 && aIdx[0]==oldVal) || (aIdx[0]==1 && aIdx[1]==oldVal) ){ if( (nIdx==1 && aIdx[0]==oldVal) || (aIdx[0]==1 && aIdx[1]==oldVal) ){
pBe->Delete(pCrsr, aStack[tos].n, zStack[tos]); pBex->Delete(pCrsr, aStack[tos].n, zStack[tos]);
}else{ }else{
k = aIdx[0]; k = aIdx[0];
for(j=1; j<=k && aIdx[j]!=oldVal; j++){} for(j=1; j<=k && aIdx[j]!=oldVal; j++){}
@ -2349,7 +2350,7 @@ int sqliteVdbeExec(
if( aIdx[0]*3 + 1 < nIdx ){ if( aIdx[0]*3 + 1 < nIdx ){
nIdx /= 2; nIdx /= 2;
} }
pBe->Put(pCrsr, aStack[tos].n, zStack[tos], pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
sizeof(int)*nIdx, (char*)aIdx); sizeof(int)*nIdx, (char*)aIdx);
} }
} }
@ -2365,7 +2366,7 @@ int sqliteVdbeExec(
** from the disk. ** from the disk.
*/ */
case OP_Destroy: { case OP_Destroy: {
pBe->DropTable(pBe, pOp->p3); pBex->DropTable(pBe, pOp->p3);
break; break;
} }
@ -2374,7 +2375,7 @@ int sqliteVdbeExec(
** Compress, optimize, and tidy up the GDBM file named by P3. ** Compress, optimize, and tidy up the GDBM file named by P3.
*/ */
case OP_Reorganize: { case OP_Reorganize: {
pBe->ReorganizeTable(pBe, pOp->p3); pBex->ReorganizeTable(pBe, pOp->p3);
break; break;
} }
@ -2396,9 +2397,9 @@ int sqliteVdbeExec(
for(j=p->nList; j<=i; j++) p->apList[j] = 0; for(j=p->nList; j<=i; j++) p->apList[j] = 0;
p->nList = i+1; p->nList = i+1;
}else if( p->apList[i] ){ }else if( p->apList[i] ){
pBe->CloseTempFile(pBe, p->apList[i]); pBex->CloseTempFile(pBe, p->apList[i]);
} }
rc = pBe->OpenTempFile(pBe, &p->apList[i]); rc = pBex->OpenTempFile(pBe, &p->apList[i]);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
sqliteSetString(pzErrMsg, "unable to open a temporary file", 0); sqliteSetString(pzErrMsg, "unable to open a temporary file", 0);
} }
@ -2468,7 +2469,7 @@ int sqliteVdbeExec(
int i = pOp->p1; int i = pOp->p1;
VERIFY( if( i<0 ) goto bad_instruction; ) VERIFY( if( i<0 ) goto bad_instruction; )
if( VERIFY( i<p->nList && ) p->apList[i]!=0 ){ if( VERIFY( i<p->nList && ) p->apList[i]!=0 ){
pBe->CloseTempFile(pBe, p->apList[i]); pBex->CloseTempFile(pBe, p->apList[i]);
p->apList[i] = 0; p->apList[i] = 0;
} }
break; break;