Changes to the DBBE.  Moving toward having many more
backend driver choices. (CVS 176)

FossilOrigin-Name: c0730217a04323a1a73d125e3e7da32bcc8d58fc
diff --git a/src/dbbe.c b/src/dbbe.c
index 43948c1..907aa73 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.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"
 
@@ -62,3 +62,90 @@
   }
   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);
+}
diff --git a/src/dbbe.h b/src/dbbe.h
index 7c54a77..7d524cb 100644
--- a/src/dbbe.h
+++ b/src/dbbe.h
@@ -28,7 +28,7 @@
 ** This library was originally designed to support the following
 ** 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_
 #define _SQLITE_DBBE_H_
@@ -53,7 +53,7 @@
 */
 typedef struct Dbbe Dbbe;
 typedef struct DbbeCursor DbbeCursor;
-
+typedef struct DbbeMethods DbbeMethods;
 
 /*
 ** Open a complete database.
@@ -65,10 +65,13 @@
 Dbbe *sqliteDbbeOpen(const char *zName, int write, int create, char **pzErr);
 
 /*
-** This is the structure returned by sqliteDbbeOpen().  It contains pointers
-** to all access routines for the database backend.
+** Each of the various SQLite backends defines a set of methods for
+** 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. */
   void (*Close)(Dbbe*);
 
@@ -149,4 +152,22 @@
   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_) */
diff --git a/src/dbbegdbm.c b/src/dbbegdbm.c
index 1e27020..6c2659a 100644
--- a/src/dbbegdbm.c
+++ b/src/dbbegdbm.c
@@ -30,7 +30,7 @@
 ** relatively simple to convert to a different database such
 ** 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 <gdbm.h>
@@ -58,33 +58,14 @@
 };
 
 /*
-** 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
 ** database driver.  This is a subclass of the Dbbe structure.
 */
 typedef struct Dbbex Dbbex;
 struct Dbbex {
   Dbbe dbbe;         /* The base class */
-  char *zDir;        /* The directory containing the database */
   int write;         /* True for write permission */
   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 @@
 };
 
 /*
-** 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;
-}
-
+struct DbbeList {
+  FILE *pOut;
+  Dbbe *pDbbe;
+};
 /*
 ** The "mkdir()" function only takes one argument under Windows.
 */
@@ -165,18 +117,7 @@
     memset(pFile, 0, sizeof(*pFile));   
     sqliteFree(pFile);
   }
-  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);
+  sqliteDbbeCloseAllTempFiles(pDbbe);
   memset(pBe, 0, sizeof(*pBe));
   sqliteFree(pBe);
 }
@@ -190,9 +131,9 @@
 static char *sqliteFileOfTable(Dbbex *pBe, const char *zTable){
   char *zFile = 0;
   int i;
-  sqliteSetString(&zFile, pBe->zDir, "/", zTable, ".tbl", 0);
+  sqliteSetString(&zFile, pBe->dbbe.zDir, "/", zTable, ".tbl", 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];
     if( isupper(c) ){
       zFile[i] = tolower(c);
@@ -204,27 +145,6 @@
 }
 
 /*
-** 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
 ** DbbeCursor structure into *ppCursr.  Return an integer success
 ** code:
@@ -295,13 +215,11 @@
       }
     }else{
       int limit;
-      struct rc4 *pRc4;
       char zRandom[50];
-      pRc4 = &pBe->rc4;
       zFile = 0;
       limit = 5;
       do {
-        randomName(&pBe->rc4, zRandom, "_temp_table_");
+        sqliteRandomName(zRandom, "_temp_table_");
         sqliteFree(zFile);
         zFile = sqliteFileOfTable(pBe, zRandom);
         pFile->dbf = gdbm_open(zFile, 0, rw_mask, mode, 0);
@@ -577,15 +495,10 @@
   datum key;
   int go = 1;
   int i;
-  struct rc4 *pRc4;
 
   if( pCursr->pFile==0 || pCursr->pFile->dbf==0 ) return 1;
-  pRc4 = &pCursr->pBe->rc4;
   while( go ){
-    iKey = 0;
-    for(i=0; i<4; i++){
-      iKey = (iKey<<8) + rc4byte(pRc4);
-    }
+    iKey = sqliteRandomInteger();
     if( iKey==0 ) continue;
     key.dptr = (char*)&iKey;
     key.dsize = 4;
@@ -631,68 +544,31 @@
 }
 
 /*
-** 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.
+** This variable contains pointers to all of the access methods
+** used to implement the GDBM backend.
 */
-static int sqliteGdbmOpenTempFile(Dbbe *pDbbe, 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 */
-  Dbbex *pBe = (Dbbex*)pDbbe;
-
-  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;
-  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);
-}
+static struct DbbeMethods gdbmMethods = {
+  /* n         Close */   sqliteGdbmClose,
+  /*      OpenCursor */   sqliteGdbmOpenCursor,
+  /*       DropTable */   sqliteGdbmDropTable,
+  /* ReorganizeTable */   sqliteGdbmReorganizeTable,
+  /*     CloseCursor */   sqliteGdbmCloseCursor,
+  /*           Fetch */   sqliteGdbmFetch,
+  /*            Test */   sqliteGdbmTest,
+  /*         CopyKey */   sqliteGdbmCopyKey,
+  /*        CopyData */   sqliteGdbmCopyData,
+  /*         ReadKey */   sqliteGdbmReadKey,
+  /*        ReadData */   sqliteGdbmReadData,
+  /*       KeyLength */   sqliteGdbmKeyLength,
+  /*      DataLength */   sqliteGdbmDataLength,
+  /*         NextKey */   sqliteGdbmNextKey,
+  /*          Rewind */   sqliteGdbmRewind,
+  /*             New */   sqliteGdbmNew,
+  /*             Put */   sqliteGdbmPut,
+  /*          Delete */   sqliteGdbmDelete,
+  /*    OpenTempFile */   sqliteDbbeOpenTempFile,
+  /*   CloseTempFile */   sqliteDbbeCloseTempFile
+};
 
 
 /*
@@ -746,31 +622,10 @@
     sqliteSetString(pzErrMsg, "out of memory", 0);
     return 0;
   }
-  pNew->dbbe.Close = sqliteGdbmClose;
-  pNew->dbbe.OpenCursor = sqliteGdbmOpenCursor;
-  pNew->dbbe.DropTable = sqliteGdbmDropTable;
-  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->dbbe.x = &gdbmMethods;
+  pNew->dbbe.zDir = (char*)&pNew[1];
+  strcpy(pNew->dbbe.zDir, zName);
   pNew->write = writeFlag;
   pNew->pOpen = 0;
-  time(&statbuf.st_ctime);
-  rc4init(&pNew->rc4, (char*)&statbuf, sizeof(statbuf));
   return &pNew->dbbe;
 }
diff --git a/src/dbbemem.c b/src/dbbemem.c
index c811805..89b4aee 100644
--- a/src/dbbemem.c
+++ b/src/dbbemem.c
@@ -28,7 +28,7 @@
 **
 ** 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 <sys/stat.h>
@@ -343,20 +343,6 @@
 };
 
 /*
-** 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
 ** database driver.  This is a subclass of the Dbbe structure.
 */
@@ -364,10 +350,6 @@
 struct Dbbex {
   Dbbe dbbe;         /* The base class */
   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 */
 };
 
 /*
@@ -386,42 +368,6 @@
 };
 
 /*
-** 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
 */
 static void sqliteMemCloseCursor(DbbeCursor *pCursr);
@@ -453,44 +399,12 @@
     deleteMTable(pTble);
   }
   ArrayClear(&pBe->tables);
-  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);
+  sqliteDbbeCloseAllTempFiles(pDbbe);
   memset(pBe, 0, sizeof(*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
 ** canonical name.
 ** 
@@ -752,14 +666,9 @@
   Datum key;
   int go = 1;
   int i;
-  struct rc4 *pRc4;
 
-  pRc4 = &pCursr->pBe->rc4;
   while( go ){
-    iKey = 0;
-    for(i=0; i<4; i++){
-      iKey = (iKey<<8) + rc4byte(pRc4);
-    }
+    iKey = sqliteRandomInteger();
     if( iKey==0 ) continue;
     key.p = (char*)&iKey;
     key.n = 4;
@@ -804,69 +713,31 @@
 }
 
 /*
-** 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.
+** This variable contains pointers to all of the access methods
+** used to implement the MEMORY backend.
 */
-static int sqliteMemOpenTempFile(Dbbe *pDbbe, FILE **ppTble){
-  char *zName;         /* 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 */
-  Dbbex *pBe = (Dbbex*)pDbbe;
-
-  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 ){
-    *ppTble = 0;
-    return SQLITE_NOMEM;
-  }
-  limit = 4;
-  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);
-}
-
+static struct DbbeMethods memoryMethods = {
+  /* n         Close */   sqliteMemClose,
+  /*      OpenCursor */   sqliteMemOpenCursor,
+  /*       DropTable */   sqliteMemDropTable,
+  /* ReorganizeTable */   sqliteMemReorganizeTable,
+  /*     CloseCursor */   sqliteMemCloseCursor,
+  /*           Fetch */   sqliteMemFetch,
+  /*            Test */   sqliteMemTest,
+  /*         CopyKey */   sqliteMemCopyKey,
+  /*        CopyData */   sqliteMemCopyData,
+  /*         ReadKey */   sqliteMemReadKey,
+  /*        ReadData */   sqliteMemReadData,
+  /*       KeyLength */   sqliteMemKeyLength,
+  /*      DataLength */   sqliteMemDataLength,
+  /*         NextKey */   sqliteMemNextKey,
+  /*          Rewind */   sqliteMemRewind,
+  /*             New */   sqliteMemNew,
+  /*             Put */   sqliteMemPut,
+  /*          Delete */   sqliteMemDelete,
+  /*    OpenTempFile */   sqliteDbbeOpenTempFile,
+  /*   CloseTempFile */   sqliteDbbeCloseTempFile
+};
 
 /*
 ** This routine opens a new database.  For the GDBM driver
@@ -884,7 +755,6 @@
   char **pzErrMsg        /* Write error messages (if any) here */
 ){
   Dbbex *pNew;
-  long now;
 
   pNew = sqliteMalloc( sizeof(*pNew) );
   if( pNew==0 ){
@@ -892,27 +762,7 @@
     return 0;
   }
   ArrayInit(&pNew->tables);
-  pNew->dbbe.Close = sqliteMemClose;
-  pNew->dbbe.OpenCursor = sqliteMemOpenCursor;
-  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));
+  pNew->dbbe.x = &memoryMethods;
+  pNew->dbbe.zDir = 0;
   return &pNew->dbbe;
 }
diff --git a/src/main.c b/src/main.c
index 0a21177..a707b67 100644
--- a/src/main.c
+++ b/src/main.c
@@ -26,7 +26,7 @@
 ** other files are for internal use by SQLite and should not be
 ** 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"
 
@@ -239,7 +239,7 @@
 */
 void sqlite_close(sqlite *db){
   int i;
-  db->pBe->Close(db->pBe);
+  db->pBe->x->Close(db->pBe);
   for(i=0; i<N_HASH; i++){
     Table *pNext, *pList = db->apTblHash[i];
     db->apTblHash[i] = 0;
diff --git a/src/random.c b/src/random.c
new file mode 100644
index 0000000..726fefe
--- /dev/null
+++ b/src/random.c
@@ -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;
+}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 5b777ef..b6e6021 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -23,7 +23,7 @@
 *************************************************************************
 ** 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 "dbbe.h"
@@ -419,3 +419,8 @@
 int sqliteExprAnalyzeAggregates(Parse*, Expr*);
 void sqliteParseInfoReset(Parse*);
 Vdbe *sqliteGetVdbe(Parse*);
+int sqliteRandomByte(void);
+int sqliteRandomInteger(void);
+void sqliteRandomName(char*,char*);
+int sqliteDbbeOpenTempFile(Dbbe*, FILE**);
+void sqliteDbbeCloseTempFile(Dbbe*, FILE*);
diff --git a/src/vdbe.c b/src/vdbe.c
index bfdb65b..749f1e0 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.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 <unistd.h>
@@ -696,7 +696,7 @@
   p->azColName = 0;
   for(i=0; i<p->nCursor; i++){
     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;
     }
   }
@@ -713,7 +713,7 @@
   p->nMem = 0;
   for(i=0; i<p->nList; 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;
     }
   }
@@ -953,6 +953,7 @@
   Op *pOp;                   /* Current operation */
   int rc;                    /* Value to return */
   Dbbe *pBe = p->pBe;        /* The backend driver */
+  DbbeMethods *pBex = pBe->x;  /* The backend driver methods */
   sqlite *db = p->db;        /* The database */
   char **zStack;
   Stack *aStack;
@@ -1809,10 +1810,10 @@
           for(j=p->nCursor; j<=i; j++) p->aCsr[j].pCursor = 0;
           p->nCursor = i+1;
         }else if( p->aCsr[i].pCursor ){
-          pBe->CloseCursor(p->aCsr[i].pCursor);
+          pBex->CloseCursor(p->aCsr[i].pCursor);
         }
         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 ){
             case SQLITE_BUSY: {
               if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){
@@ -1853,7 +1854,7 @@
       case OP_Close: {
         int i = pOp->p1;
         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;
         }
         break;
@@ -1871,11 +1872,11 @@
         VERIFY( if( tos<0 ) goto not_enough_stack; )
         if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){
           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);
           }else{
             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]);
           }
           p->nFetch++;
@@ -1937,11 +1938,11 @@
         VERIFY( if( tos<0 ) goto not_enough_stack; )
         if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor ){
           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);
           }else{
             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]);
           }
         }
@@ -1967,7 +1968,7 @@
         if( VERIFY( i<0 || i>=p->nCursor || ) p->aCsr[i].pCursor==0 ){
           v = 0;
         }else{
-          v = pBe->New(p->aCsr[i].pCursor);
+          v = pBex->New(p->aCsr[i].pCursor);
         }
         VERIFY( NeedStack(p, p->tos+1); )
         p->tos++;
@@ -2000,7 +2001,7 @@
             nKey = sizeof(int);
             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]);
         }
         POPSTACK;
@@ -2028,7 +2029,7 @@
             nKey = aStack[tos].n;
             zKey = zStack[tos];
           }
-          pBe->Delete(p->aCsr[i].pCursor, nKey, zKey);
+          pBex->Delete(p->aCsr[i].pCursor, nKey, zKey);
         }
         POPSTACK;
         break;
@@ -2082,29 +2083,29 @@
         VERIFY( if( NeedStack(p, tos) ) goto no_mem; )
         if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
           if( p->aCsr[i].keyAsData ){
-            amt = pBe->KeyLength(pCrsr);
+            amt = pBex->KeyLength(pCrsr);
             if( amt<=sizeof(int)*(p2+1) ){
               aStack[tos].flags = STK_Null;
               break;
             }
-            pAddr = (int*)pBe->ReadKey(pCrsr, sizeof(int)*p2);
+            pAddr = (int*)pBex->ReadKey(pCrsr, sizeof(int)*p2);
             if( *pAddr==0 ){
               aStack[tos].flags = STK_Null;
               break;
             }
-            z = pBe->ReadKey(pCrsr, *pAddr);
+            z = pBex->ReadKey(pCrsr, *pAddr);
           }else{
-            amt = pBe->DataLength(pCrsr);
+            amt = pBex->DataLength(pCrsr);
             if( amt<=sizeof(int)*(p2+1) ){
               aStack[tos].flags = STK_Null;
               break;
             }
-            pAddr = (int*)pBe->ReadData(pCrsr, sizeof(int)*p2);
+            pAddr = (int*)pBex->ReadData(pCrsr, sizeof(int)*p2);
             if( *pAddr==0 ){
               aStack[tos].flags = STK_Null;
               break;
             }
-            z = pBe->ReadData(pCrsr, *pAddr);
+            z = pBex->ReadData(pCrsr, *pAddr);
           }
           zStack[tos] = z;
           aStack[tos].n = strlen(z) + 1;
@@ -2127,11 +2128,11 @@
 
         VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
         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 ){
             zStack[tos] = z;
             aStack[tos].flags = STK_Str;
-            aStack[tos].n = pBe->KeyLength(pCrsr);
+            aStack[tos].n = pBex->KeyLength(pCrsr);
           }else{
             memcpy(&aStack[tos].i, z, sizeof(int));
             aStack[tos].flags = STK_Int;
@@ -2148,7 +2149,7 @@
       case OP_Rewind: {
         int i = pOp->p1;
         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;
       }
@@ -2161,7 +2162,7 @@
       case OP_Next: {
         int i = pOp->p1;
         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;
           }else{
             p->nFetch++;
@@ -2211,8 +2212,8 @@
           int *aIdx;
           int nIdx;
           int j, k;
-          nIdx = pBe->DataLength(pCrsr)/sizeof(int);
-          aIdx = (int*)pBe->ReadData(pCrsr, 0);
+          nIdx = pBex->DataLength(pCrsr)/sizeof(int);
+          aIdx = (int*)pBex->ReadData(pCrsr, 0);
           if( nIdx>1 ){
             k = *(aIdx++);
             if( k>nIdx-1 ) k = nIdx-1;
@@ -2257,10 +2258,10 @@
           Integerify(p, nos);
           newVal = aStack[nos].i;
           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 ){
             /* 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);
           }else{
             /* Extend the existing record */
@@ -2268,32 +2269,32 @@
             int *aIdx;
             int k;
             
-            nIdx = pBe->DataLength(pCrsr)/sizeof(int);
+            nIdx = pBex->DataLength(pCrsr)/sizeof(int);
             if( nIdx==1 ){
               aIdx = sqliteMalloc( sizeof(int)*4 );
               if( aIdx==0 ) goto no_mem;
               aIdx[0] = 2;
-              pBe->CopyData(pCrsr, 0, sizeof(int), (char*)&aIdx[1]);
+              pBex->CopyData(pCrsr, 0, sizeof(int), (char*)&aIdx[1]);
               aIdx[2] = newVal;
-              pBe->Put(pCrsr, aStack[tos].n, zStack[tos],
+              pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
                     sizeof(int)*4, (char*)aIdx);
               sqliteFree(aIdx);
             }else{
-              aIdx = (int*)pBe->ReadData(pCrsr, 0);
+              aIdx = (int*)pBex->ReadData(pCrsr, 0);
               k = aIdx[0];
               if( k<nIdx-1 ){
                 aIdx[k+1] = newVal;
                 aIdx[0]++;
-                pBe->Put(pCrsr, aStack[tos].n, zStack[tos],
+                pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
                     sizeof(int)*nIdx, (char*)aIdx);
               }else{
                 nIdx *= 2;
                 aIdx = sqliteMalloc( sizeof(int)*nIdx );
                 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[0]++;
-                pBe->Put(pCrsr, aStack[tos].n, zStack[tos],
+                pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
                       sizeof(int)*nIdx, (char*)aIdx);
                 sqliteFree(aIdx);
               }
@@ -2333,12 +2334,12 @@
           Integerify(p, nos);
           oldVal = aStack[nos].i;
           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;
-          nIdx = pBe->DataLength(pCrsr)/sizeof(int);
-          aIdx = (int*)pBe->ReadData(pCrsr, 0);
+          nIdx = pBex->DataLength(pCrsr)/sizeof(int);
+          aIdx = (int*)pBex->ReadData(pCrsr, 0);
           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{
             k = aIdx[0];
             for(j=1; j<=k && aIdx[j]!=oldVal; j++){}
@@ -2349,7 +2350,7 @@
             if( aIdx[0]*3 + 1 < nIdx ){
               nIdx /= 2;
             }
-            pBe->Put(pCrsr, aStack[tos].n, zStack[tos], 
+            pBex->Put(pCrsr, aStack[tos].n, zStack[tos], 
                           sizeof(int)*nIdx, (char*)aIdx);
           }
         }
@@ -2365,7 +2366,7 @@
       ** from the disk.
       */
       case OP_Destroy: {
-        pBe->DropTable(pBe, pOp->p3);
+        pBex->DropTable(pBe, pOp->p3);
         break;
       }
 
@@ -2374,7 +2375,7 @@
       ** Compress, optimize, and tidy up the GDBM file named by P3.
       */
       case OP_Reorganize: {
-        pBe->ReorganizeTable(pBe, pOp->p3);
+        pBex->ReorganizeTable(pBe, pOp->p3);
         break;
       }
 
@@ -2396,9 +2397,9 @@
           for(j=p->nList; j<=i; j++) p->apList[j] = 0;
           p->nList = i+1;
         }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 ){
           sqliteSetString(pzErrMsg, "unable to open a temporary file", 0);
         }
@@ -2468,7 +2469,7 @@
         int i = pOp->p1;
         VERIFY( if( i<0 ) goto bad_instruction; )
         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;
         }
         break;