mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-01 06:27:03 +03:00
Misc cleanup. Notes on compiling for Win95. (CVS 152)
FossilOrigin-Name: 3f0f1fa1fce794d1661c845f1a63a8d744892c25
This commit is contained in:
@ -57,6 +57,7 @@ SRC = \
|
|||||||
$(TOP)/src/build.c \
|
$(TOP)/src/build.c \
|
||||||
$(TOP)/src/dbbe.c \
|
$(TOP)/src/dbbe.c \
|
||||||
$(TOP)/src/dbbe.h \
|
$(TOP)/src/dbbe.h \
|
||||||
|
$(TOP)/src/dbbemem.c \
|
||||||
$(TOP)/src/delete.c \
|
$(TOP)/src/delete.c \
|
||||||
$(TOP)/src/expr.c \
|
$(TOP)/src/expr.c \
|
||||||
$(TOP)/src/insert.c \
|
$(TOP)/src/insert.c \
|
||||||
|
3276
contrib/dlmalloc.c
Normal file
3276
contrib/dlmalloc.c
Normal file
File diff suppressed because it is too large
Load Diff
34
manifest
34
manifest
@ -1,33 +1,35 @@
|
|||||||
C Version\s1.0.9\s(CVS\s493)
|
C Misc\scleanup.\s\sNotes\son\scompiling\sfor\sWin95.\s(CVS\s152)
|
||||||
D 2000-10-09T22:30:00
|
D 2000-10-11T19:28:51
|
||||||
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
|
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
|
||||||
F Makefile.in f0b70aaa6717f9454c787dc74e5504c98ae7ea18
|
F Makefile.in faecea9b6419cec25030b4818c9b3f7f4163b3c1
|
||||||
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
|
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
|
||||||
F VERSION 1fe894c9b80001e9dbc3b40ef1f4f984c9b624f3
|
F VERSION 0302755bd219af2c39c53cc097caccb858798223
|
||||||
F configure 3dc1edb9dcf60215e31ff72b447935ab62211442 x
|
F configure 3dc1edb9dcf60215e31ff72b447935ab62211442 x
|
||||||
F configure.in d892ca33db7e88a055519ce2f36dcb11020e8fff
|
F configure.in d892ca33db7e88a055519ce2f36dcb11020e8fff
|
||||||
|
F contrib/dlmalloc.c 754f43cd3b225728017b2516a58103f4bc3f05ee
|
||||||
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
|
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
|
||||||
F src/build.c 4d90e9e94750ca80249fc7958c617021d8bb7a50
|
F src/build.c 4d90e9e94750ca80249fc7958c617021d8bb7a50
|
||||||
F src/dbbe.c 226daaf8c095ceb4aff48cad188dad90643f9867
|
F src/dbbe.c 226daaf8c095ceb4aff48cad188dad90643f9867
|
||||||
F src/dbbe.h 6337132f904e72ecb28b07390021c241397e4cbf
|
F src/dbbe.h 6337132f904e72ecb28b07390021c241397e4cbf
|
||||||
|
F src/dbbemem.c eb3d79be7105bd80069815ee499c8e8682876378
|
||||||
F src/delete.c 4d491eaf61b515516749c7ed68fa3b2ee8a09065
|
F src/delete.c 4d491eaf61b515516749c7ed68fa3b2ee8a09065
|
||||||
F src/expr.c e8e350d7baa33bd9ed8701c159eaba5e912e0adb
|
F src/expr.c e8e350d7baa33bd9ed8701c159eaba5e912e0adb
|
||||||
F src/insert.c f146f149ad2422a1dc3bfa7a1651a25940f98958
|
F src/insert.c f146f149ad2422a1dc3bfa7a1651a25940f98958
|
||||||
F src/main.c 9a89579b40e498920f86e89878f52185457b9c2c
|
F src/main.c 03ca6d7601b40a3c6de95d7f8c6c817e8cca9fdf
|
||||||
F src/parse.y 5d199034de5d29ebedb42c1c51f34db4df40cbe5
|
F src/parse.y 5d199034de5d29ebedb42c1c51f34db4df40cbe5
|
||||||
F src/printf.c 534954b942046761e0860c30a9031fa9d803ca3c
|
F src/printf.c 6fc343f0c3537e2530a11ac164ce64ba171aebf8
|
||||||
F src/select.c d382e96c2221d08367cc87976f2b574537c9de97
|
F src/select.c d382e96c2221d08367cc87976f2b574537c9de97
|
||||||
F src/shell.c ef5d12129c824cb98238763e9e86ca1847e0c7bd
|
F src/shell.c ef5d12129c824cb98238763e9e86ca1847e0c7bd
|
||||||
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
|
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
|
||||||
F src/sqlite.h.in 7a11f9d131e9657d11dee5c23dfe458da91de8e2
|
F src/sqlite.h.in 7a11f9d131e9657d11dee5c23dfe458da91de8e2
|
||||||
F src/sqliteInt.h b65fdecac7281aafb4c9ff3e79ea1b5546478385
|
F src/sqliteInt.h b65fdecac7281aafb4c9ff3e79ea1b5546478385
|
||||||
F src/table.c 12f0165b47178b54a675d25ed373ee7e798d6ff0
|
F src/table.c f08189678c806d8a74a70c156d7c27083760e028
|
||||||
F src/tclsqlite.c 7ccccae67fb36ed60ec98282953bf5dad0f9c16f
|
F src/tclsqlite.c 44b08b47612a668caaf7c4ec32133b69d73ff78e
|
||||||
F src/tokenize.c 097bec5843d4a0fb4509e036fee93bac080c5e73
|
F src/tokenize.c 097bec5843d4a0fb4509e036fee93bac080c5e73
|
||||||
F src/update.c 51b9ef7434b15e31096155da920302e9db0d27fc
|
F src/update.c 51b9ef7434b15e31096155da920302e9db0d27fc
|
||||||
F src/util.c 782f87af3c48c898631a2d5b7074437c899f6f13
|
F src/util.c 811e0ad47f842c16555aaf361b26dab7221c1a6c
|
||||||
F src/vdbe.c c0e3d29d2e13997d5664ade19ff2c8e2212945e3
|
F src/vdbe.c b8b0bc26d6543d5d33820809122bf0e7659e4663
|
||||||
F src/vdbe.h 6413cd0165ac62b0839fe3e077cb7c9f0b736295
|
F src/vdbe.h 8ca755f77eeaa93886d25188fd66129febfa16cf
|
||||||
F src/where.c 3dfad2ffd0aa994d5eceac88852f7189c8d1d3c8
|
F src/where.c 3dfad2ffd0aa994d5eceac88852f7189c8d1d3c8
|
||||||
F test/all.test 0950c135cab7e60c07bd745ccfad1476211e5bd7
|
F test/all.test 0950c135cab7e60c07bd745ccfad1476211e5bd7
|
||||||
F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
|
F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
|
||||||
@ -64,8 +66,8 @@ F www/arch.fig 4f246003b7da23bd63b8b0af0618afb4ee3055c8
|
|||||||
F www/arch.png 8dae0766d42ed3de9ed013c1341a5792bcf633e6
|
F www/arch.png 8dae0766d42ed3de9ed013c1341a5792bcf633e6
|
||||||
F www/arch.tcl a40380c1fe0080c43e6cc5c20ed70731511b06be
|
F www/arch.tcl a40380c1fe0080c43e6cc5c20ed70731511b06be
|
||||||
F www/c_interface.tcl 03f5fe8f2da9713aa1748f7e4ce34a0c35926ac9
|
F www/c_interface.tcl 03f5fe8f2da9713aa1748f7e4ce34a0c35926ac9
|
||||||
F www/changes.tcl 9f98c996ce4f60d082deab9b29c2d7f7981ea680
|
F www/changes.tcl fcd35239062ac03d6169506ae8ef19189979c8f1
|
||||||
F www/crosscompile.tcl 19734ce7f18b16ff2ed8479412abf8aca56e1dcc
|
F www/crosscompile.tcl bee79c34f6c3f162ec1c6f5294e79f73651d27ee
|
||||||
F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9
|
F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9
|
||||||
F www/index.tcl b19418d506f90968deef972bf1b427d98bdf13e0
|
F www/index.tcl b19418d506f90968deef972bf1b427d98bdf13e0
|
||||||
F www/lang.tcl 9192e114b19987e630a41e879585b87006eb84a1
|
F www/lang.tcl 9192e114b19987e630a41e879585b87006eb84a1
|
||||||
@ -74,7 +76,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
|
|||||||
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
|
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
|
||||||
F www/tclsqlite.tcl ae101d5f7c07dcc59770e2a84aae09025fab2dad
|
F www/tclsqlite.tcl ae101d5f7c07dcc59770e2a84aae09025fab2dad
|
||||||
F www/vdbe.tcl bcbfc33bcdd0ebad95eab31286adb9e1bc289520
|
F www/vdbe.tcl bcbfc33bcdd0ebad95eab31286adb9e1bc289520
|
||||||
P 15340d2bb34c4d7ab629f9fa2231c7f34a248db9
|
P ebbb9e4a660e833efddb7ffea737135fff3bf2f5
|
||||||
R 02bf6b83b2b17b70d381cfc976f772c2
|
R 0e3d2b823401c2dde691e21fb25d6652
|
||||||
U drh
|
U drh
|
||||||
Z 35d8208b4df3d6667977ea9f36f5d1b8
|
Z faddfef9a141ecc95fe77c48bb93186c
|
||||||
|
@ -1 +1 @@
|
|||||||
ebbb9e4a660e833efddb7ffea737135fff3bf2f5
|
3f0f1fa1fce794d1661c845f1a63a8d744892c25
|
766
src/dbbemem.c
Normal file
766
src/dbbemem.c
Normal file
@ -0,0 +1,766 @@
|
|||||||
|
/*
|
||||||
|
** Copyright (c) 1999, 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 the database backend (DBBE)
|
||||||
|
** for sqlite. The database backend is the interface between
|
||||||
|
** sqlite and the code that does the actually reading and writing
|
||||||
|
** of information to the disk.
|
||||||
|
**
|
||||||
|
** This file implements a backend that constructs a database in
|
||||||
|
** memory using hash tables. Nothing is ever read or written
|
||||||
|
** to disk. Everything is forgotten when the program exits.
|
||||||
|
**
|
||||||
|
** $Id: dbbemem.c,v 1.1 2000/10/11 19:28:52 drh Exp $
|
||||||
|
*/
|
||||||
|
#include "sqliteInt.h"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Key or data is stored as an instance of the following
|
||||||
|
*/
|
||||||
|
typedef struct datum {
|
||||||
|
void *dptr; /* The data */
|
||||||
|
int dsize; /* Number of bytes of data */
|
||||||
|
void *kptr; /* The key */
|
||||||
|
int ksize; /* Number of bytes of key */
|
||||||
|
datum *pHash; /* Next datum with the same hash */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Information about each open database table is an instance of this
|
||||||
|
** structure. There will only be one such structure for each
|
||||||
|
** table. If the VDBE opens the same table twice (as will happen
|
||||||
|
** for a self-join, for example) then two DbbeCursor structures are
|
||||||
|
** created but there is only a single BeFile structure with an
|
||||||
|
** nRef of 2.
|
||||||
|
*/
|
||||||
|
typedef struct BeFile BeFile;
|
||||||
|
struct BeFile {
|
||||||
|
char *zName; /* Name of the table */
|
||||||
|
BeFile *pNext, *pPrev; /* Next and previous on list of all tables */
|
||||||
|
BeFile *pHash; /* Next table with same hash on zName */
|
||||||
|
int nRef; /* Number of cursor that have this file open */
|
||||||
|
int delOnClose; /* Delete when the last cursor closes this file */
|
||||||
|
int nRec; /* Number of entries in the hash table */
|
||||||
|
int nHash; /* Number of slots in the hash table */
|
||||||
|
datum **aHash; /* The hash table */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The complete database is an instance of the following structure.
|
||||||
|
*/
|
||||||
|
struct Dbbe {
|
||||||
|
BeFile *pOpen; /* List of open tables */
|
||||||
|
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 */
|
||||||
|
BeFile aHash[331]; /* Hash table of tables */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** An cursor into a database file is an instance of the following structure.
|
||||||
|
** There can only be a single BeFile structure for each disk file, but
|
||||||
|
** there can be multiple DbbeCursor structures. Each DbbeCursor represents
|
||||||
|
** a cursor pointing to a particular part of the open BeFile. The
|
||||||
|
** BeFile.nRef field hold a count of the number of DbbeCursor structures
|
||||||
|
** associated with the same disk file.
|
||||||
|
*/
|
||||||
|
struct DbbeCursor {
|
||||||
|
Dbbe *pBe; /* The database of which this record is a part */
|
||||||
|
BeFile *pFile; /* The database file for this table */
|
||||||
|
datum *pRec; /* Most recently used key and data */
|
||||||
|
int h; /* Hash of pRec */
|
||||||
|
int needRewind; /* Next key should be the first */
|
||||||
|
int readPending; /* The fetch hasn't actually been done yet */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This routine opens a new database. For the GDBM driver
|
||||||
|
** implemented here, the database name is the name of the directory
|
||||||
|
** containing all the files of the database.
|
||||||
|
**
|
||||||
|
** If successful, a pointer to the Dbbe structure is returned.
|
||||||
|
** If there are errors, an appropriate error message is left
|
||||||
|
** in *pzErrMsg and NULL is returned.
|
||||||
|
*/
|
||||||
|
Dbbe *sqliteDbbeOpen(
|
||||||
|
const char *zName, /* The name of the database */
|
||||||
|
int writeFlag, /* True if we will be writing to the database */
|
||||||
|
int createFlag, /* True to create database if it doesn't exist */
|
||||||
|
char **pzErrMsg /* Write error messages (if any) here */
|
||||||
|
){
|
||||||
|
Dbbe *pNew;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
pNew = sqliteMalloc(sizeof(Dbbe));
|
||||||
|
if( pNew==0 ){
|
||||||
|
sqliteSetString(pzErrMsg, "out of memory", 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pNew->pOpen = 0;
|
||||||
|
time(&now);
|
||||||
|
rc4init(&pNew->rc4, (char*)&now, sizeof(now));
|
||||||
|
return pNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Free all of the memory associated with a single BeFile structure.
|
||||||
|
** It is assumed that this BeFile structure has already been unlinked
|
||||||
|
** from its database.
|
||||||
|
*/
|
||||||
|
static void sqliteDbbeFreeFile(BeFile *pFile){
|
||||||
|
int i;
|
||||||
|
for(i=0; i<pFile->nHash; i++){
|
||||||
|
datum *pDatum, *pNextDatum;
|
||||||
|
for(pDatum = pFile->aHash[i]; pDatum; pDatum=pNextDatum){
|
||||||
|
pNextDatum = pDatum->pHash;
|
||||||
|
sqliteFree(pDatum->dptr);
|
||||||
|
sqliteFree(pDatum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqliteFree(pFile->zName);
|
||||||
|
sqliteFree(pFile->aHash);
|
||||||
|
memset(pFile, 0, sizeof(*pFile));
|
||||||
|
sqliteFree(pFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Completely shutdown the given database. Close all files. Free all memory.
|
||||||
|
*/
|
||||||
|
void sqliteDbbeClose(Dbbe *pBe){
|
||||||
|
BeFile *pFile, *pNext;
|
||||||
|
int i;
|
||||||
|
for(pFile=pBe->pOpen; pFile; pFile=pNext){
|
||||||
|
pNext = pFile->pNext;
|
||||||
|
sqliteDbbeFreeFile(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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Hash a NULL-terminated string.
|
||||||
|
*/
|
||||||
|
static int sqliteStrHash(const char *z){
|
||||||
|
int h = 0;
|
||||||
|
while( *z ){
|
||||||
|
h = (h<<3) ^ h ^ *(z++);
|
||||||
|
}
|
||||||
|
if( h<0 ) h = -h;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Locate a file in a database
|
||||||
|
*/
|
||||||
|
static BeFile *sqliteDbbeFindFile(Dbbe *pBe, const char *zFile){
|
||||||
|
int h;
|
||||||
|
BeFile *pFile;
|
||||||
|
|
||||||
|
h = sqliteStrHash(zFile) % (sizeof(pBe->aHash)/sizeof(pBe->aHash[0]));
|
||||||
|
for(pFile=pBe->aHash[h]; pFile; pFile=pFile->pHash){
|
||||||
|
if( strcmp(pFile->zName, zFile)==0 ) break;
|
||||||
|
}
|
||||||
|
return pFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Open a new table cursor. Write a pointer to the corresponding
|
||||||
|
** DbbeCursor structure into *ppCursr. Return an integer success
|
||||||
|
** code:
|
||||||
|
**
|
||||||
|
** SQLITE_OK It worked!
|
||||||
|
**
|
||||||
|
** SQLITE_NOMEM sqliteMalloc() failed
|
||||||
|
**
|
||||||
|
** SQLITE_PERM Attempt to access a file for which file
|
||||||
|
** access permission is denied
|
||||||
|
**
|
||||||
|
** SQLITE_BUSY Another thread or process is already using
|
||||||
|
** the corresponding file and has that file locked.
|
||||||
|
**
|
||||||
|
** SQLITE_READONLY The current thread already has this file open
|
||||||
|
** readonly but you are trying to open for writing.
|
||||||
|
** (This can happen if a SELECT callback tries to
|
||||||
|
** do an UPDATE or DELETE.)
|
||||||
|
**
|
||||||
|
** If zTable is 0 or "", then a temporary database file is created and
|
||||||
|
** a cursor to that temporary file is opened. The temporary file
|
||||||
|
** will be deleted from the disk when it is closed.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeOpenCursor(
|
||||||
|
Dbbe *pBe, /* The database the table belongs to */
|
||||||
|
const char *zTable, /* The SQL name of the file to be opened */
|
||||||
|
int writeable, /* True to open for writing */
|
||||||
|
DbbeCursor **ppCursr /* Write the resulting table pointer here */
|
||||||
|
){
|
||||||
|
char *zFile; /* Name of the table file */
|
||||||
|
DbbeCursor *pCursr; /* The new table cursor */
|
||||||
|
BeFile *pFile; /* The underlying data file for this table */
|
||||||
|
int rc = SQLITE_OK; /* Return value */
|
||||||
|
int rw_mask; /* Permissions mask for opening a table */
|
||||||
|
int mode; /* Mode for opening a table */
|
||||||
|
|
||||||
|
*ppCursr = 0;
|
||||||
|
pCursr = sqliteMalloc( sizeof(*pCursr) );
|
||||||
|
if( pCursr==0 ) return SQLITE_NOMEM;
|
||||||
|
if( zTable ){
|
||||||
|
zFile = sqliteStrDup(zTable);
|
||||||
|
pFile = sqliteDbbeFindFile(zFile);
|
||||||
|
}else{
|
||||||
|
pFile = 0;
|
||||||
|
zFile = 0;
|
||||||
|
}
|
||||||
|
if( pFile==0 ){
|
||||||
|
pFile = sqliteMalloc( sizeof(*pFile) );
|
||||||
|
if( pFile==0 ){
|
||||||
|
sqliteFree(zFile);
|
||||||
|
return SQLITE_NOMEM;
|
||||||
|
}
|
||||||
|
if( zFile ){
|
||||||
|
if( !writeable || pBe->write ){
|
||||||
|
pFile->dbf = gdbm_open(zFile, 0, rw_mask, mode, 0);
|
||||||
|
}else{
|
||||||
|
pFile->dbf = 0;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
int limit;
|
||||||
|
struct rc4 *pRc4;
|
||||||
|
char zRandom[50];
|
||||||
|
pRc4 = &pBe->rc4;
|
||||||
|
zFile = 0;
|
||||||
|
limit = 5;
|
||||||
|
while( 1 ){
|
||||||
|
randomName(&pBe->rc4, zRandom, "_temp_table_");
|
||||||
|
sqliteFree(zFile);
|
||||||
|
zFile = sqliteStrDup(zRandom);
|
||||||
|
if( sqliteDbbeFindFile(pBe, zFile)==0 ) break;
|
||||||
|
}
|
||||||
|
pFile->delOnClose = 1;
|
||||||
|
}
|
||||||
|
pFile->zName = zFile;
|
||||||
|
pFile->nRef = 1;
|
||||||
|
pFile->pPrev = 0;
|
||||||
|
if( pBe->pOpen ){
|
||||||
|
pBe->pOpen->pPrev = pFile;
|
||||||
|
}
|
||||||
|
pFile->pNext = pBe->pOpen;
|
||||||
|
pBe->pOpen = pFile;
|
||||||
|
}else{
|
||||||
|
sqliteFree(zFile);
|
||||||
|
pFile->nRef++;
|
||||||
|
}
|
||||||
|
pCursr->pBe = pBe;
|
||||||
|
pCursr->pFile = pFile;
|
||||||
|
pCursr->readPending = 0;
|
||||||
|
pCursr->needRewind = 1;
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
sqliteDbbeCloseCursor(pCursr);
|
||||||
|
*ppCursr = 0;
|
||||||
|
}else{
|
||||||
|
*ppCursr = pCursr;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Unlink a file from the database
|
||||||
|
*/
|
||||||
|
static void sqliteDbbeUnlinkFile(Dbbe *pBe, BeFile *pFile){
|
||||||
|
int h = sqliteStrHash(pFile->zName) %
|
||||||
|
(sizeof(pBe->aHash)/sizeof(pBe->aHash[0])));
|
||||||
|
if( pBe->aHash[h]==pFile ){
|
||||||
|
pBe->aHash[h] = pFile->pHash;
|
||||||
|
}else{
|
||||||
|
BeFile *pProbe;
|
||||||
|
for(pProbe=pBe->aHash[h]; pProbe; pProbe=pProbe->pHash){
|
||||||
|
if( pProbe->pHash==pFile ){
|
||||||
|
pProbe->pHash = pFile->pHash;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Drop a table from the database. The file that corresponds
|
||||||
|
** to this table is deleted.
|
||||||
|
*/
|
||||||
|
void sqliteDbbeDropTable(Dbbe *pBe, const char *zTable){
|
||||||
|
File *pFile;
|
||||||
|
|
||||||
|
pFile = sqliteDbbeFindFile(pBe, zTable);
|
||||||
|
if( pFile ){
|
||||||
|
sqliteDbbeUnlinkFile(pFile);
|
||||||
|
sqliteDbbeFreeFile(pFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Reorganize a table to reduce search times and disk usage.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeReorganizeTable(Dbbe *pBe, const char *zTable){
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Close a cursor previously opened by sqliteDbbeOpenCursor().
|
||||||
|
**
|
||||||
|
** There can be multiple cursors pointing to the same open file.
|
||||||
|
** The underlying file is not closed until all cursors have been
|
||||||
|
** closed. This routine decrements the BeFile.nref field of the
|
||||||
|
** underlying file and closes the file when nref reaches 0.
|
||||||
|
*/
|
||||||
|
void sqliteDbbeCloseCursor(DbbeCursor *pCursr){
|
||||||
|
BeFile *pFile;
|
||||||
|
Dbbe *pBe;
|
||||||
|
if( pCursr==0 ) return;
|
||||||
|
pFile = pCursr->pFile;
|
||||||
|
pBe = pCursr->pBe;
|
||||||
|
pFile->nRef--;
|
||||||
|
if( pFile->nRef<=0 ){
|
||||||
|
if( pFile->pPrev ){
|
||||||
|
pFile->pPrev->pNext = pFile->pNext;
|
||||||
|
}else{
|
||||||
|
pBe->pOpen = pFile->pNext;
|
||||||
|
}
|
||||||
|
if( pFile->pNext ){
|
||||||
|
pFile->pNext->pPrev = pFile->pPrev;
|
||||||
|
}
|
||||||
|
if( pFile->delOnClose ){
|
||||||
|
sqliteDbbeUnlinkFile(pFile);
|
||||||
|
sqliteDbbeFreeFile(pFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(pCursr, 0, sizeof(*pCursr));
|
||||||
|
sqliteFree(pCursr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Compute a hash on binary data
|
||||||
|
*/
|
||||||
|
static int sqliteBinaryHash(int n, char *z){
|
||||||
|
int h = 0;
|
||||||
|
while( n-- ){
|
||||||
|
h = (h<<9) ^ (h<<3) ^ h ^ *(z++);
|
||||||
|
}
|
||||||
|
if( h<0 ) h = -h;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Resize the hash table
|
||||||
|
*/
|
||||||
|
static void sqliteDbbeRehash(BeFile *pFile, int nHash){
|
||||||
|
int i, h;
|
||||||
|
datum *pRec, *pNextRec;
|
||||||
|
datum **aHash;
|
||||||
|
|
||||||
|
if( nHash<1 ) return;
|
||||||
|
aHash = sqliteMalloc( sizeof(aHash[0])*nHash );
|
||||||
|
if( aHash==0 ) return;
|
||||||
|
for(i=0; i<pFile->nHash; i++){
|
||||||
|
for(pRec=pFile->aHash[i]; pRec; pRec=pNextRec){
|
||||||
|
pNextRec = pRec->pHash;
|
||||||
|
h = sqliteBinaryHash(pRec->ksize, pRec->kptr) % nHash;
|
||||||
|
pRec->pHash = aHash[h];
|
||||||
|
aHash[h] = pRec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqliteFree(pFile->aHash);
|
||||||
|
pFile->aHash = aHash;
|
||||||
|
pFile->nHash = nHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Locate a datum in a file. Create it if it isn't already there and
|
||||||
|
** the createFlag is set.
|
||||||
|
*/
|
||||||
|
static datum **sqliteDbbeLookup(
|
||||||
|
BeFile *pFile, /* Where to look */
|
||||||
|
int nKey, /* The size of the key */
|
||||||
|
char *pKey, /* The key */
|
||||||
|
int *pH, /* Write the hash line here */
|
||||||
|
int createFlag /* Create a new entry if this is true */
|
||||||
|
){
|
||||||
|
int h;
|
||||||
|
datum **ppRec = 0;
|
||||||
|
datum *pNew;
|
||||||
|
if( pFile->nHash>0 ){
|
||||||
|
h = sqliteBinaryHash(nKey, pKey) % pFile->nHash;
|
||||||
|
ppRec = &pFile->aHash[h];
|
||||||
|
while( *ppRec ){
|
||||||
|
if( (**ppRec).ksize==nKey && memcpy((**ppRec).kptr, pKey, nKey)==0 ){
|
||||||
|
if( *pH ) *pH = h;
|
||||||
|
return ppRec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( createFlag==0 ) return 0;
|
||||||
|
if( (pFile->nRec + 1) > pFile->nHash*2 ){
|
||||||
|
int nHash = (pFile->nRec + 1)*4;
|
||||||
|
if( nHash<51 ) nHash = 51;
|
||||||
|
sqliteDbbeRehash(pFile, nHash);
|
||||||
|
if( pFile->nHash==0 ) return 0;
|
||||||
|
}
|
||||||
|
h = sqliteBinaryHash(nKey, pKey) % pFile->nHash;
|
||||||
|
pNew = sqliteMalloc( sizeof(*pNew) + nKey );
|
||||||
|
if( pNew==0 ) return 0;
|
||||||
|
pNew->kptr = (void*)&pNew[1];
|
||||||
|
pNew->ksize = nKey;
|
||||||
|
memcpy(pNew->kptr, pkey, nKey);
|
||||||
|
pNew->pHash = pFile->aHash[h];
|
||||||
|
pFile->aHash[h] = pNew;
|
||||||
|
pNew->dsize = 0;
|
||||||
|
pNew->dptr = 0;
|
||||||
|
pFile->nRec++;
|
||||||
|
if( pH ) *pH = h;
|
||||||
|
return &pFile->aHash[h];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Fetch a single record from an open cursor. Return 1 on success
|
||||||
|
** and 0 on failure.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeFetch(DbbeCursor *pCursr, int nKey, char *pKey){
|
||||||
|
datum **ppRec;
|
||||||
|
ppRec = sqliteDbbeLookup(pCursr->pFile, nKey, pKey, &pCursr->h, 0);
|
||||||
|
if( ppRec ){
|
||||||
|
pCursr->pRec = *ppRec;
|
||||||
|
}
|
||||||
|
return pCursr->pRec!=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return 1 if the given key is already in the table. Return 0
|
||||||
|
** if it is not.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeTest(DbbeCursor *pCursr, int nKey, char *pKey){
|
||||||
|
return sqliteDbbeFetch(pCursr, nKey, pKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copy bytes from the current key or data into a buffer supplied by
|
||||||
|
** the calling function. Return the number of bytes copied.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeCopyKey(DbbeCursor *pCursr, int offset, int size, char *zBuf){
|
||||||
|
int n;
|
||||||
|
datum *pRec;
|
||||||
|
if( (pRec = pCursor->pRec)==0 || offset>=pRec->ksize ) return 0;
|
||||||
|
if( offset+size>pRec->ksize ){
|
||||||
|
n = pRec->ksize - offset;
|
||||||
|
}else{
|
||||||
|
n = size;
|
||||||
|
}
|
||||||
|
memcpy(zBuf, pRec->kptr[offset], n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
int sqliteDbbeCopyData(DbbeCursor *pCursr, int offset, int size, char *zBuf){
|
||||||
|
int n;
|
||||||
|
datum *pRec;
|
||||||
|
if( (pRec = pCursr->pRec)==0 || offset>=pRec->dsize ) return 0;
|
||||||
|
if( offset+size>pRec->dsize ){
|
||||||
|
n = pRec->dsize - offset;
|
||||||
|
}else{
|
||||||
|
n = size;
|
||||||
|
}
|
||||||
|
memcpy(zBuf, &pRec->dptr[offset], n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return a pointer to bytes from the key or data. The data returned
|
||||||
|
** is ephemeral.
|
||||||
|
*/
|
||||||
|
char *sqliteDbbeReadKey(DbbeCursor *pCursr, int offset){
|
||||||
|
datum *pRec;
|
||||||
|
if( (pRec = pCursr->pRec)==0 || offset<0 || offset>=pRec->ksize ) return "";
|
||||||
|
return &pRec->kptr[offset];
|
||||||
|
}
|
||||||
|
char *sqliteDbbeReadData(DbbeCursor *pCursr, int offset){
|
||||||
|
datum *pRec;
|
||||||
|
if( (pRec = pCursr->pRec)==0 || offset<0 || offset>=pRec->dsize ) return "";
|
||||||
|
return &pRec->dptr[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return the total number of bytes in either data or key.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeKeyLength(DbbeCursor *pCursr){
|
||||||
|
return pCursr->pRec ? pCursor->pRec->ksize : 0;
|
||||||
|
}
|
||||||
|
int sqliteDbbeDataLength(DbbeCursor *pCursr){
|
||||||
|
return pCursr->pRec ? pCursor->pRec->dsize : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Make is so that the next call to sqliteNextKey() finds the first
|
||||||
|
** key of the table.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeRewind(DbbeCursor *pCursr){
|
||||||
|
pCursr->needRewind = 1;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Read the next key from the table. Return 1 on success. Return
|
||||||
|
** 0 if there are no more keys.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeNextKey(DbbeCursor *pCursr){
|
||||||
|
int h;
|
||||||
|
BeFile *pFile;
|
||||||
|
if( pCursr==0 || (pFile = pCursr->pFile)==0 || pFile->nHash==0 ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if( pCursr->needRewind ){
|
||||||
|
pCursr->pRec = 0;
|
||||||
|
pCursr->h = -1;
|
||||||
|
}
|
||||||
|
if( pCursr->pRec ){
|
||||||
|
pCursr->pRec = pCursr->pRec->pHash;
|
||||||
|
}
|
||||||
|
if( pCursr->pRec==0 ){
|
||||||
|
for(h=pCursr->h; h<pFile->nHash && pFile->aHash[h]==0; h++){}
|
||||||
|
if( h>=pFile->nHash ){
|
||||||
|
pCursr->h = -1;
|
||||||
|
return 0;
|
||||||
|
}else{
|
||||||
|
pCursr->h = h;
|
||||||
|
pCursr->pRec = pFile->aHash[h];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Get a new integer key.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeNew(DbbeCursor *pCursr){
|
||||||
|
int iKey;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if( iKey==0 ) continue;
|
||||||
|
go = sqliteDbbeLookup(pCursr->pFile, sizeof(iKey), &iKey, 0, 0)!=0;
|
||||||
|
}
|
||||||
|
return iKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Write an entry into the table. Overwrite any prior entry with the
|
||||||
|
** same key.
|
||||||
|
*/
|
||||||
|
int sqliteDbbePut(
|
||||||
|
DbbeCursor *pCursr, /* Write to this cursor */
|
||||||
|
int nKey, /* Size of the key */
|
||||||
|
char *pKey, /* The key */
|
||||||
|
int nData, /* Size of the data */
|
||||||
|
char *pData /* The data */
|
||||||
|
){
|
||||||
|
int rc;
|
||||||
|
datum **ppRec, *pRec;
|
||||||
|
if( pCursr->pFile==0 ) return SQLITE_ERROR;
|
||||||
|
ppRec = sqliteDbbeLookup(pCursr->pFile, nKey, pKey, &pCursr->h, 1);
|
||||||
|
if( ppRec==0 ) return SQLITE_NOMEM;
|
||||||
|
pRec = *ppRec;
|
||||||
|
sqliteFree(pRec->dptr);
|
||||||
|
pRec->dptr = sqliteMalloc( nData );
|
||||||
|
if( pRec->dptr==0 ) return SQLITE_NOMEM;
|
||||||
|
memcpy(pRec->dptr, pData, nData);
|
||||||
|
pRec->dsize = nData;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Remove an entry from a table, if the entry exists.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeDelete(DbbeCursor *pCursr, int nKey, char *pKey){
|
||||||
|
datum **ppRec, *pRec;
|
||||||
|
ppRec = sqliteDbbeLookcup(pCursr->pFile, nKey, pKey, 0, 0);
|
||||||
|
if( ppRec ){
|
||||||
|
pRec = *ppRec;
|
||||||
|
*ppRec = pRec->pNext;
|
||||||
|
if( pCursr->pRec==pRec ){
|
||||||
|
pCursr->pRec = 0;
|
||||||
|
pCursr->h = -1;
|
||||||
|
}
|
||||||
|
sqliteFree(pRec->dptr);
|
||||||
|
sqliteFree(pRec);
|
||||||
|
pCursr->pFile->nRec--;
|
||||||
|
}
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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 */
|
||||||
|
|
||||||
|
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 sqliteDbbeOpenTempFile()
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
@ -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.18 2000/08/22 13:40:51 drh Exp $
|
** $Id: main.c,v 1.19 2000/10/11 19:28:52 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -327,7 +327,6 @@ static int sqlite_default_busy_callback(
|
|||||||
const char *NotUsed, /* The name of the table that is busy */
|
const char *NotUsed, /* The name of the table that is busy */
|
||||||
int count /* Number of times table has been busy */
|
int count /* Number of times table has been busy */
|
||||||
){
|
){
|
||||||
int rc;
|
|
||||||
#if defined(HAVE_USLEEP) && HAVE_USLEEP
|
#if defined(HAVE_USLEEP) && HAVE_USLEEP
|
||||||
int delay = 10000;
|
int delay = 10000;
|
||||||
int prior_delay = 0;
|
int prior_delay = 0;
|
||||||
|
@ -46,7 +46,9 @@
|
|||||||
** + All functions are fully reentrant.
|
** + All functions are fully reentrant.
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
#include <ctype.h>
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Undefine COMPATIBILITY to make some slight changes in the way things
|
** Undefine COMPATIBILITY to make some slight changes in the way things
|
||||||
** work. I think the changes are an improvement, but they are not
|
** work. I think the changes are an improvement, but they are not
|
||||||
|
@ -31,8 +31,8 @@ typedef struct TabResult {
|
|||||||
static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
|
static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
|
||||||
TabResult *p = (TabResult*)pArg;
|
TabResult *p = (TabResult*)pArg;
|
||||||
int need;
|
int need;
|
||||||
int i, len;
|
int i;
|
||||||
char *z, *zVal;
|
char *z;
|
||||||
|
|
||||||
/* Make sure there is enough space in p->azResult to hold everything
|
/* Make sure there is enough space in p->azResult to hold everything
|
||||||
** we need to remember from this invocation of the callback.
|
** we need to remember from this invocation of the callback.
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** A TCL Interface to SQLite
|
** A TCL Interface to SQLite
|
||||||
**
|
**
|
||||||
** $Id: tclsqlite.c,v 1.10 2000/09/30 22:46:07 drh Exp $
|
** $Id: tclsqlite.c,v 1.11 2000/10/11 19:28:52 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
|
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
|
||||||
|
|
||||||
@ -138,7 +138,6 @@ static int DbBusyHandler(void *cd, const char *zTable, int nTries){
|
|||||||
int rc;
|
int rc;
|
||||||
char zVal[30];
|
char zVal[30];
|
||||||
char *zCmd;
|
char *zCmd;
|
||||||
char *zResult;
|
|
||||||
Tcl_DString cmd;
|
Tcl_DString cmd;
|
||||||
|
|
||||||
Tcl_DStringInit(&cmd);
|
Tcl_DStringInit(&cmd);
|
||||||
|
16
src/util.c
16
src/util.c
@ -26,15 +26,18 @@
|
|||||||
** This file contains functions for allocating memory, comparing
|
** This file contains functions for allocating memory, comparing
|
||||||
** strings, and stuff like that.
|
** strings, and stuff like that.
|
||||||
**
|
**
|
||||||
** $Id: util.c,v 1.15 2000/09/14 01:21:10 drh Exp $
|
** $Id: util.c,v 1.16 2000/10/11 19:28:52 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If MEMORY_DEBUG is defined, then use versions of malloc() and
|
||||||
|
** free() that track memory usage and check for buffer overruns.
|
||||||
|
*/
|
||||||
#ifdef MEMORY_DEBUG
|
#ifdef MEMORY_DEBUG
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Allocate new memory and set it to zero. Return NULL if
|
** Allocate new memory and set it to zero. Return NULL if
|
||||||
** no memory is available.
|
** no memory is available.
|
||||||
@ -164,9 +167,14 @@ char *sqliteStrNDup_(const char *z, int n, char *zFile, int line){
|
|||||||
}
|
}
|
||||||
return zNew;
|
return zNew;
|
||||||
}
|
}
|
||||||
|
#endif /* MEMORY_DEBUG */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The following versions of malloc() and free() are for use in a
|
||||||
|
** normal build.
|
||||||
|
*/
|
||||||
|
#if !defined(MEMORY_DEBUG)
|
||||||
|
|
||||||
#else /* !defined(MEMORY_DEBUG) */
|
|
||||||
/*
|
/*
|
||||||
** Allocate new memory and set it to zero. Return NULL if
|
** Allocate new memory and set it to zero. Return NULL if
|
||||||
** no memory is available.
|
** no memory is available.
|
||||||
@ -219,7 +227,7 @@ char *sqliteStrNDup(const char *z, int n){
|
|||||||
}
|
}
|
||||||
return zNew;
|
return zNew;
|
||||||
}
|
}
|
||||||
#endif /* MEMORY_DEBUG */
|
#endif /* !defined(MEMORY_DEBUG) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Create a string from the 2nd and subsequent arguments (up to the
|
** Create a string from the 2nd and subsequent arguments (up to the
|
||||||
|
@ -41,10 +41,11 @@
|
|||||||
** 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.41 2000/09/14 01:21:10 drh Exp $
|
** $Id: vdbe.c,v 1.42 2000/10/11 19:28:53 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** SQL is translated into a sequence of instructions to be
|
** SQL is translated into a sequence of instructions to be
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
** or VDBE. The VDBE implements an abstract machine that runs a
|
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||||
** simple program to access and modify the underlying database.
|
** simple program to access and modify the underlying database.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.h,v 1.12 2000/08/28 15:51:45 drh Exp $
|
** $Id: vdbe.h,v 1.13 2000/10/11 19:28:53 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE_VDBE_H_
|
#ifndef _SQLITE_VDBE_H_
|
||||||
#define _SQLITE_VDBE_H_
|
#define _SQLITE_VDBE_H_
|
||||||
@ -196,6 +196,6 @@ int sqliteVdbeList(Vdbe*,sqlite_callback,void*,char**);
|
|||||||
void sqliteVdbeResolveLabel(Vdbe*, int);
|
void sqliteVdbeResolveLabel(Vdbe*, int);
|
||||||
int sqliteVdbeCurrentAddr(Vdbe*);
|
int sqliteVdbeCurrentAddr(Vdbe*);
|
||||||
void sqliteVdbeTrace(Vdbe*,FILE*);
|
void sqliteVdbeTrace(Vdbe*,FILE*);
|
||||||
|
void sqliteVdbeCompressSpace(Vdbe*,int);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,6 +17,12 @@ proc chng {date desc} {
|
|||||||
puts "<DD><P><UL>$desc</UL></P></DD>"
|
puts "<DD><P><UL>$desc</UL></P></DD>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chng {2000 Oct 11 (Not Released)} {
|
||||||
|
<li>Added notes on how to compile for Windows95/98.</li>
|
||||||
|
<li>Add Doug Lea's memory allocator to the distribution, for completeness.</li>
|
||||||
|
<li>Removed a few variables that were not being used. Etc.</li>
|
||||||
|
}
|
||||||
|
|
||||||
chng {2000 Oct 8 (1.0.9)} {
|
chng {2000 Oct 8 (1.0.9)} {
|
||||||
<li>Added the <b>sqlite_..._printf()</b> interface routines.</li>
|
<li>Added the <b>sqlite_..._printf()</b> interface routines.</li>
|
||||||
<li>Modified the <b>sqlite</b> shell program to use the new interface
|
<li>Modified the <b>sqlite</b> shell program to use the new interface
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Run this Tcl script to generate the crosscompile.html file.
|
# Run this Tcl script to generate the crosscompile.html file.
|
||||||
#
|
#
|
||||||
set rcsid {$Id: crosscompile.tcl,v 1.2 2000/07/31 19:16:32 drh Exp $}
|
set rcsid {$Id: crosscompile.tcl,v 1.3 2000/10/11 19:28:53 drh Exp $}
|
||||||
|
|
||||||
puts {<html>
|
puts {<html>
|
||||||
<head>
|
<head>
|
||||||
@ -23,7 +23,9 @@ binaries. See the website for details.</p>
|
|||||||
|
|
||||||
<p>This page describes how you can use MinGW configured as a
|
<p>This page describes how you can use MinGW configured as a
|
||||||
cross-compiler running under RedHat 6.0 Linux to generate a
|
cross-compiler running under RedHat 6.0 Linux to generate a
|
||||||
binary for SQLite that runs under WinNT.</p>
|
binary for SQLite that runs under WinNT.
|
||||||
|
Some additional steps (described <a href="#win95">below</a>)
|
||||||
|
are needed to target Win95/98.</p>
|
||||||
}
|
}
|
||||||
|
|
||||||
proc Code {body} {
|
proc Code {body} {
|
||||||
@ -123,6 +125,64 @@ make
|
|||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
<a name="win95">
|
||||||
|
<h2>Targetting Windows95/98 instead of WindowsNT</h2>
|
||||||
|
|
||||||
|
<p>A small amount of additional work is needed to get SQLite running
|
||||||
|
under Windows95/98. The first problem is that the LockFile() and
|
||||||
|
UnlockFile() API that the Roth GDBM port uses does not work under
|
||||||
|
Windows95. The easiest workaround is to just disable file locking
|
||||||
|
in the GDBM library. You can do so by appending a few lines of code
|
||||||
|
to the end of one of the GDBM source files and compiling the library
|
||||||
|
using a special command-line option. Replace step (4) above as
|
||||||
|
follows:</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li value="4"><p>
|
||||||
|
Append text to the <b>systems.h</b> source file as follows:</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
cat >>systems.h <<\END
|
||||||
|
#ifdef NO_LOCKS
|
||||||
|
#undef UNLOCK_FILE
|
||||||
|
#define UNLOCK_FILE(x)
|
||||||
|
#undef READLOCK_FILE
|
||||||
|
#define READLOCK_FILE(x)
|
||||||
|
#undef WRITELOCK_FILE
|
||||||
|
#define WRITELOCK_FILE(x)
|
||||||
|
#endif
|
||||||
|
END
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>Then manually build the GDBM library with the extra
|
||||||
|
"NO_LOCKS" define as follows:</p>
|
||||||
|
<blockquote><pre>
|
||||||
|
i386-mingw32-gcc -DWIN32=1 -DNO_LOCKS -O2 -c *.c
|
||||||
|
i386-mingw32-ar cr libgdbm.a *.o
|
||||||
|
i386-mingw32-ranlib libgdbm.a
|
||||||
|
cd ..
|
||||||
|
</pre></blockquote>
|
||||||
|
</p></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>Note that the locking problem has been reported and may actually
|
||||||
|
be fixed in the Roth GDBM distribution by the time you read this.
|
||||||
|
You should probably check before you make the above changes.</p>
|
||||||
|
|
||||||
|
<p>The above is all you have to do to get SQLite to work on Windows95.
|
||||||
|
But one more step is required to get it to work <i>well</i>. It
|
||||||
|
turns out that SQLite make heavy use of <b>malloc()</b> and
|
||||||
|
<b>free()</b> and the implementation of this functions
|
||||||
|
on Windows95 is particular poor. Large database queries will run
|
||||||
|
more than 10 times faster if you substitute a better memory allocator
|
||||||
|
such as the one by
|
||||||
|
<a href="http://g.oswego.edu/dl/html/malloc.html">Doug Lea</a>.
|
||||||
|
A copy of Doug's allocator is included in the <b>contrib</b>
|
||||||
|
directory of the source tree. Speed improvements are also reported
|
||||||
|
on WindowsNT when alternative memory allocators are used, though
|
||||||
|
the speedup is not as dramatic as it is with WIndows95.</p>
|
||||||
|
|
||||||
}
|
}
|
||||||
puts {
|
puts {
|
||||||
<p><hr /></p>
|
<p><hr /></p>
|
||||||
|
Reference in New Issue
Block a user