mirror of
				https://github.com/sqlite/sqlite.git
				synced 2025-11-03 16:53:36 +03:00 
			
		
		
		
	Changes to the DBBE. Moving toward having many more
backend driver choices. (CVS 176) FossilOrigin-Name: c0730217a04323a1a73d125e3e7da32bcc8d58fc
This commit is contained in:
		@@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								manifest
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								manifest
									
									
									
									
									
								
							@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1 @@
 | 
				
			|||||||
46b86abb1cc8e550acddba24e510d36eaf8ac6b9
 | 
					c0730217a04323a1a73d125e3e7da32bcc8d58fc
 | 
				
			||||||
							
								
								
									
										89
									
								
								src/dbbe.c
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								src/dbbe.c
									
									
									
									
									
								
							@@ -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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								src/dbbe.h
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								src/dbbe.h
									
									
									
									
									
								
							@@ -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_) */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										221
									
								
								src/dbbegdbm.c
									
									
									
									
									
								
							
							
						
						
									
										221
									
								
								src/dbbegdbm.c
									
									
									
									
									
								
							@@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										208
									
								
								src/dbbemem.c
									
									
									
									
									
								
							
							
						
						
									
										208
									
								
								src/dbbemem.c
									
									
									
									
									
								
							@@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
									
								
							
							
						
						
									
										127
									
								
								src/random.c
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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*);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										89
									
								
								src/vdbe.c
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								src/vdbe.c
									
									
									
									
									
								
							@@ -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;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user