mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
added DISTINCT on select (CVS 27)
FossilOrigin-Name: 1f0c4ffd98591e506201b6b0e6e60b9216ceb596
This commit is contained in:
28
manifest
28
manifest
@@ -1,5 +1,5 @@
|
|||||||
C :-)\s(CVS\s26)
|
C added\sDISTINCT\son\sselect\s(CVS\s27)
|
||||||
D 2000-05-31T18:33:10
|
D 2000-05-31T20:00:52
|
||||||
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
|
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
|
||||||
F Makefile.in 7ac2fef265940d93a544cb454efa836451559a71
|
F Makefile.in 7ac2fef265940d93a544cb454efa836451559a71
|
||||||
F README 6b5960603c7f8bf42fc022b4b6436f242f238dbb
|
F README 6b5960603c7f8bf42fc022b4b6436f242f238dbb
|
||||||
@@ -7,23 +7,23 @@ F configure 00a5b5c82147a576fa6e82d7c1b0d55c321d6d2c x
|
|||||||
F configure.in 6ccfd5fc80517f7cfe605a7fc7e0f62d962a233c
|
F configure.in 6ccfd5fc80517f7cfe605a7fc7e0f62d962a233c
|
||||||
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
|
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
|
||||||
F src/build.c 03f83e95d46e328a2ac08aace102b142ea38e6d7
|
F src/build.c 03f83e95d46e328a2ac08aace102b142ea38e6d7
|
||||||
F src/dbbe.c dc9439f839d13e633158808e352056b531f17e1b
|
F src/dbbe.c 80080f5ef2297e54797ee24f5951dab1c39af5d5
|
||||||
F src/dbbe.h b678e31c32fa252e6fba830ad16ed8978d1521a9
|
F src/dbbe.h 0147c9f8539d421d6c5558d3e854b78387372fae
|
||||||
F src/delete.c 16ef3418b19be9ab39db836c693970ca7bbff605
|
F src/delete.c 16ef3418b19be9ab39db836c693970ca7bbff605
|
||||||
F src/expr.c 91970700e3e39b2b725b028c166f588a5bb0c038
|
F src/expr.c 91970700e3e39b2b725b028c166f588a5bb0c038
|
||||||
F src/insert.c bd34716d0bba5561f6b55101adbf16fa75f872e8
|
F src/insert.c bd34716d0bba5561f6b55101adbf16fa75f872e8
|
||||||
F src/main.c 25cce7bce0eb3ba10bada7c05f4b38dc6dbbc86f
|
F src/main.c 25cce7bce0eb3ba10bada7c05f4b38dc6dbbc86f
|
||||||
F src/parse.y 038e0f0fd243b89344c974c5d0552e85c4d27916
|
F src/parse.y 16322c46ec117082ef745715f7a4761f2491a0b2
|
||||||
F src/select.c 719ca9605a351b2a3521a692ae8d2936d4832609
|
F src/select.c 25cada7cb2b0b4973b3e17c81ba1b1c887829f71
|
||||||
F src/shell.c c5752d32cdeaa7d548d4f91177b697b023a00381
|
F src/shell.c c5752d32cdeaa7d548d4f91177b697b023a00381
|
||||||
F src/sqlite.h 2397c17a8f4ca90c09acab0100dc7e2f8f441b69
|
F src/sqlite.h 2397c17a8f4ca90c09acab0100dc7e2f8f441b69
|
||||||
F src/sqliteInt.h 81552acdedb0c3b256510a66c0f656d35d2ea2bd
|
F src/sqliteInt.h 04f38613a8ecedfdb15b21175acf0fe2ce55e299
|
||||||
F src/tclsqlite.c 9efd29f79ded6a900aa3d142169c8bfe03b7affd
|
F src/tclsqlite.c 9efd29f79ded6a900aa3d142169c8bfe03b7affd
|
||||||
F src/tokenize.c 5b066f314646d6c5396a253315e5e95d107e1800
|
F src/tokenize.c 15c229fee77325334c6814652e429b0930eba6c1
|
||||||
F src/update.c 9194f548dafc9884d79489874e22974ed67cd6a2
|
F src/update.c 9194f548dafc9884d79489874e22974ed67cd6a2
|
||||||
F src/util.c 6b4327d7fbf684f8635155d4acb847ae991b3ebc
|
F src/util.c 6b4327d7fbf684f8635155d4acb847ae991b3ebc
|
||||||
F src/vdbe.c 11d8e4f6e25044ceace5e7a5c160b74b0537492c
|
F src/vdbe.c a60a9316f2ffbc020d5a9a73535b84e7f513e45d
|
||||||
F src/vdbe.h 02b470d344caed04451c896be7a775068dbdf076
|
F src/vdbe.h ab574c91c6328c5795f68b84074fbcf860eae70e
|
||||||
F src/where.c bed9a8360cbfbf712bdc397c8e22216a5e5f9800
|
F src/where.c bed9a8360cbfbf712bdc397c8e22216a5e5f9800
|
||||||
F test/all.test 66a8a5b8291a472157944edcdce51a320ebd1f35
|
F test/all.test 66a8a5b8291a472157944edcdce51a320ebd1f35
|
||||||
F test/copy.test 641bd3cfaab61c4ee32889587e21e4c70788a97a
|
F test/copy.test 641bd3cfaab61c4ee32889587e21e4c70788a97a
|
||||||
@@ -43,9 +43,9 @@ F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
|||||||
F tool/renumberOps.awk 6d067177ad5f8d711b79577b462da9b3634bd0a9
|
F tool/renumberOps.awk 6d067177ad5f8d711b79577b462da9b3634bd0a9
|
||||||
F www/c_interface.tcl f875864edf7974157d1c257ca08de854660882a5
|
F www/c_interface.tcl f875864edf7974157d1c257ca08de854660882a5
|
||||||
F www/changes.tcl 995d64c96978a996f0e9e46f2ce896355a7c87a7
|
F www/changes.tcl 995d64c96978a996f0e9e46f2ce896355a7c87a7
|
||||||
F www/index.tcl 600e85c207929bedb9c6fd221aa7875fd8f43edf
|
F www/index.tcl a94e31dc690f07b0dfdb82c5ab6315e4840a336d
|
||||||
F www/sqlite.tcl 7deb564df188ad4523adecfe2365de6d09f6dfd9
|
F www/sqlite.tcl 7deb564df188ad4523adecfe2365de6d09f6dfd9
|
||||||
P 35a8f523e8389a1a6e41f6561500644b165d556e
|
P 0b7d9eb8ad771917c53587ea4d674f7e8d76121f
|
||||||
R 7e04f378295246aef19c10676ba30bf8
|
R 73a74ce4d5a10f11090cf328a18ab074
|
||||||
U drh
|
U drh
|
||||||
Z 23a52b4171f3850f1bc24517d67a8aa5
|
Z ef837be79fdfd30ace7832037467a189
|
||||||
|
@@ -1 +1 @@
|
|||||||
0b7d9eb8ad771917c53587ea4d674f7e8d76121f
|
1f0c4ffd98591e506201b6b0e6e60b9216ceb596
|
185
src/dbbe.c
185
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.3 2000/05/31 02:27:49 drh Exp $
|
** $Id: dbbe.c,v 1.4 2000/05/31 20:00:52 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <gdbm.h>
|
#include <gdbm.h>
|
||||||
@@ -47,9 +47,20 @@ struct BeFile {
|
|||||||
char *zName; /* Name of the file */
|
char *zName; /* Name of the file */
|
||||||
GDBM_FILE dbf; /* The file itself */
|
GDBM_FILE dbf; /* The file itself */
|
||||||
int nRef; /* Number of references */
|
int nRef; /* Number of references */
|
||||||
|
int delOnClose; /* Delete when closing */
|
||||||
BeFile *pNext, *pPrev; /* Next and previous on list of open files */
|
BeFile *pNext, *pPrev; /* Next and previous on list of open files */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The following are state variables for the RC4 algorithm. We
|
||||||
|
** use RC4 as a random number generator. Each call to RC4 gives
|
||||||
|
** a random 8-bit number.
|
||||||
|
*/
|
||||||
|
struct rc4 {
|
||||||
|
int i, j;
|
||||||
|
int s[256];
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The complete database is an instance of the following structure.
|
** The complete database is an instance of the following structure.
|
||||||
*/
|
*/
|
||||||
@@ -59,6 +70,7 @@ struct Dbbe {
|
|||||||
BeFile *pOpen; /* List of open files */
|
BeFile *pOpen; /* List of open files */
|
||||||
int nTemp; /* Number of temporary files created */
|
int nTemp; /* Number of temporary files created */
|
||||||
FILE **apTemp; /* Space to hold temporary file pointers */
|
FILE **apTemp; /* Space to hold temporary file pointers */
|
||||||
|
struct rc4 rc4; /* The random number generator */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -74,6 +86,41 @@ struct DbbeTable {
|
|||||||
int readPending; /* The fetch hasn't actually been done yet */
|
int readPending; /* The fetch hasn't actually been done yet */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Initialize the RC4 algorithm.
|
||||||
|
*/
|
||||||
|
static void rc4init(struct rc4 *p, char *key, int keylen){
|
||||||
|
int i;
|
||||||
|
char k[256];
|
||||||
|
p->j = 0;
|
||||||
|
p->i = 0;
|
||||||
|
for(i=0; i<256; i++){
|
||||||
|
p->s[i] = i;
|
||||||
|
k[i] = key[i%keylen];
|
||||||
|
}
|
||||||
|
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 algorithm.
|
||||||
|
*/
|
||||||
|
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 current driver scheme,
|
** This routine opens a new database. For the current driver scheme,
|
||||||
** the database name is the name of the directory
|
** the database name is the name of the directory
|
||||||
@@ -105,6 +152,8 @@ Dbbe *sqliteDbbeOpen(
|
|||||||
strcpy(pNew->zDir, zName);
|
strcpy(pNew->zDir, zName);
|
||||||
pNew->write = write;
|
pNew->write = write;
|
||||||
pNew->pOpen = 0;
|
pNew->pOpen = 0;
|
||||||
|
time(&statbuf.st_ctime);
|
||||||
|
rc4init(&pNew->rc4, (char*)&statbuf, sizeof(statbuf));
|
||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +193,22 @@ static char *sqliteFileOfTable(Dbbe *pBe, const char *zTable){
|
|||||||
return zFile;
|
return zFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Generate a random filename with the given prefix.
|
||||||
|
*/
|
||||||
|
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) & 0x7f) % (sizeof(zRandomChars) - 1);
|
||||||
|
zBuf[j++] = zRandomChars[c];
|
||||||
|
}
|
||||||
|
zBuf[j] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Open a new table cursor
|
** Open a new table cursor
|
||||||
*/
|
*/
|
||||||
@@ -158,9 +223,14 @@ DbbeTable *sqliteDbbeOpenTable(
|
|||||||
|
|
||||||
pTable = sqliteMalloc( sizeof(*pTable) );
|
pTable = sqliteMalloc( sizeof(*pTable) );
|
||||||
if( pTable==0 ) return 0;
|
if( pTable==0 ) return 0;
|
||||||
zFile = sqliteFileOfTable(pBe, zTable);
|
if( zTable ){
|
||||||
for(pFile=pBe->pOpen; pFile; pFile=pFile->pNext){
|
zFile = sqliteFileOfTable(pBe, zTable);
|
||||||
if( strcmp(pFile->zName,zFile)==0 ) break;
|
for(pFile=pBe->pOpen; pFile; pFile=pFile->pNext){
|
||||||
|
if( strcmp(pFile->zName,zFile)==0 ) break;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
pFile = 0;
|
||||||
|
zFile = 0;
|
||||||
}
|
}
|
||||||
if( pFile==0 ){
|
if( pFile==0 ){
|
||||||
pFile = sqliteMalloc( sizeof(*pFile) );
|
pFile = sqliteMalloc( sizeof(*pFile) );
|
||||||
@@ -176,7 +246,24 @@ DbbeTable *sqliteDbbeOpenTable(
|
|||||||
}
|
}
|
||||||
pFile->pNext = pBe->pOpen;
|
pFile->pNext = pBe->pOpen;
|
||||||
pBe->pOpen = pFile;
|
pBe->pOpen = pFile;
|
||||||
pFile->dbf = gdbm_open(pFile->zName, 0, GDBM_WRCREAT|GDBM_FAST, 0640, 0);
|
if( pFile->zName ){
|
||||||
|
pFile->dbf = gdbm_open(pFile->zName, 0, GDBM_WRCREAT|GDBM_FAST, 0640, 0);
|
||||||
|
}else{
|
||||||
|
int i, j, limit;
|
||||||
|
struct rc4 *pRc4;
|
||||||
|
char zRandom[50];
|
||||||
|
pRc4 = &pBe->rc4;
|
||||||
|
zFile = 0;
|
||||||
|
limit = 5;
|
||||||
|
do {
|
||||||
|
randomName(&pBe->rc4, zRandom, "_temp_table_");
|
||||||
|
sqliteFree(zFile);
|
||||||
|
zFile = sqliteFileOfTable(pBe, zRandom);
|
||||||
|
pFile->dbf = gdbm_open(zFile, 0, GDBM_WRCREAT|GDBM_FAST, 0640, 0);
|
||||||
|
}while( pFile->dbf==0 && limit-- >= 0);
|
||||||
|
pFile->zName = zFile;
|
||||||
|
pFile->delOnClose = 1;
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
sqliteFree(zFile);
|
sqliteFree(zFile);
|
||||||
pFile->nRef++;
|
pFile->nRef++;
|
||||||
@@ -240,6 +327,9 @@ void sqliteDbbeCloseTable(DbbeTable *pTable){
|
|||||||
if( pFile->pNext ){
|
if( pFile->pNext ){
|
||||||
pFile->pNext->pPrev = pFile->pPrev;
|
pFile->pNext->pPrev = pFile->pPrev;
|
||||||
}
|
}
|
||||||
|
if( pFile->delOnClose ){
|
||||||
|
unlink(pFile->zName);
|
||||||
|
}
|
||||||
sqliteFree(pFile->zName);
|
sqliteFree(pFile->zName);
|
||||||
memset(pFile, 0, sizeof(*pFile));
|
memset(pFile, 0, sizeof(*pFile));
|
||||||
sqliteFree(pFile);
|
sqliteFree(pFile);
|
||||||
@@ -275,6 +365,21 @@ int sqliteDbbeFetch(DbbeTable *pTable, int nKey, char *pKey){
|
|||||||
return pTable->data.dptr!=0;
|
return pTable->data.dptr!=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return 1 if the given key is already in the table. Return 0
|
||||||
|
** if it is not.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeTest(DbbeTable *pTable, int nKey, char *pKey){
|
||||||
|
datum key;
|
||||||
|
int result = 0;
|
||||||
|
key.dsize = nKey;
|
||||||
|
key.dptr = pKey;
|
||||||
|
if( pTable->pFile && pTable->pFile->dbf ){
|
||||||
|
result = gdbm_exists(pTable->pFile->dbf, key);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Copy bytes from the current key or data into a buffer supplied by
|
** Copy bytes from the current key or data into a buffer supplied by
|
||||||
** the calling function. Return the number of bytes copied.
|
** the calling function. Return the number of bytes copied.
|
||||||
@@ -377,73 +482,22 @@ int sqliteDbbeNextKey(DbbeTable *pTable){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** The following are state variables for the RC4 algorithm. We
|
|
||||||
** use RC4 as a random number generator. Each call to RC4 gives
|
|
||||||
** a random 8-bit number.
|
|
||||||
*/
|
|
||||||
static struct {
|
|
||||||
int i, j;
|
|
||||||
int s[256];
|
|
||||||
} rc4;
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Initialize the RC4 algorithm.
|
|
||||||
*/
|
|
||||||
static void rc4init(char *key, int keylen){
|
|
||||||
int i;
|
|
||||||
char k[256];
|
|
||||||
rc4.j = 0;
|
|
||||||
rc4.i = 0;
|
|
||||||
for(i=0; i<256; i++){
|
|
||||||
rc4.s[i] = i;
|
|
||||||
k[i] = key[i%keylen];
|
|
||||||
}
|
|
||||||
for(i=0; i<256; i++){
|
|
||||||
int t;
|
|
||||||
rc4.j = (rc4.j + rc4.s[i] + k[i]) & 0xff;
|
|
||||||
t = rc4.s[rc4.j];
|
|
||||||
rc4.s[rc4.j] = rc4.s[i];
|
|
||||||
rc4.s[i] = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Get a single 8-bit random value from the RC4 algorithm.
|
|
||||||
*/
|
|
||||||
static int rc4byte(void){
|
|
||||||
int t;
|
|
||||||
rc4.i = (rc4.i + 1) & 0xff;
|
|
||||||
rc4.j = (rc4.j + rc4.s[rc4.i]) & 0xff;
|
|
||||||
t = rc4.s[rc4.i];
|
|
||||||
rc4.s[rc4.i] = rc4.s[rc4.j];
|
|
||||||
rc4.s[rc4.j] = t;
|
|
||||||
t = rc4.s[rc4.i] + rc4.s[rc4.j];
|
|
||||||
return t & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Get a new integer key.
|
** Get a new integer key.
|
||||||
*/
|
*/
|
||||||
int sqliteDbbeNew(DbbeTable *pTable){
|
int sqliteDbbeNew(DbbeTable *pTable){
|
||||||
static int isInit = 0;
|
|
||||||
int iKey;
|
int iKey;
|
||||||
datum key;
|
datum key;
|
||||||
int go = 1;
|
int go = 1;
|
||||||
int i;
|
int i;
|
||||||
|
struct rc4 *pRc4;
|
||||||
|
|
||||||
if( !isInit ){
|
|
||||||
struct stat statbuf;
|
|
||||||
stat(pTable->pFile->zName, &statbuf);
|
|
||||||
time(&statbuf.st_ctime);
|
|
||||||
rc4init((char*)&statbuf, sizeof(statbuf));
|
|
||||||
isInit = 1;
|
|
||||||
}
|
|
||||||
if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return 1;
|
if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return 1;
|
||||||
|
pRc4 = &pTable->pBe->rc4;
|
||||||
while( go ){
|
while( go ){
|
||||||
iKey = 0;
|
iKey = 0;
|
||||||
for(i=0; i<4; i++){
|
for(i=0; i<4; i++){
|
||||||
iKey = (iKey<<8) + rc4byte();
|
iKey = (iKey<<8) + rc4byte(pRc4);
|
||||||
}
|
}
|
||||||
key.dptr = (char*)&iKey;
|
key.dptr = (char*)&iKey;
|
||||||
key.dsize = 4;
|
key.dsize = 4;
|
||||||
@@ -488,8 +542,9 @@ int sqliteDbbeDelete(DbbeTable *pTable, int nKey, char *pKey){
|
|||||||
*/
|
*/
|
||||||
FILE *sqliteDbbeOpenTempFile(Dbbe *pBe){
|
FILE *sqliteDbbeOpenTempFile(Dbbe *pBe){
|
||||||
char *zFile;
|
char *zFile;
|
||||||
char zBuf[30];
|
char zBuf[50];
|
||||||
int i;
|
int i, j;
|
||||||
|
int limit;
|
||||||
|
|
||||||
for(i=0; i<pBe->nTemp; i++){
|
for(i=0; i<pBe->nTemp; i++){
|
||||||
if( pBe->apTemp[i]==0 ) break;
|
if( pBe->apTemp[i]==0 ) break;
|
||||||
@@ -499,9 +554,13 @@ FILE *sqliteDbbeOpenTempFile(Dbbe *pBe){
|
|||||||
pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) );
|
pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) );
|
||||||
}
|
}
|
||||||
if( pBe->apTemp==0 ) return 0;
|
if( pBe->apTemp==0 ) return 0;
|
||||||
sprintf(zBuf, "/_temp_%d~", i);
|
limit = 4;
|
||||||
zFile = 0;
|
zFile = 0;
|
||||||
sqliteSetString(&zFile, pBe->zDir, zBuf, 0);
|
do{
|
||||||
|
randomName(&pBe->rc4, zBuf, "/_temp_file_");
|
||||||
|
sqliteFree(zFile);
|
||||||
|
sqliteSetString(&zFile, pBe->zDir, zBuf, 0);
|
||||||
|
}while( access(zFile,0) && limit-- >= 0 );
|
||||||
pBe->apTemp[i] = fopen(zFile, "w+");
|
pBe->apTemp[i] = fopen(zFile, "w+");
|
||||||
sqliteFree(zFile);
|
sqliteFree(zFile);
|
||||||
return pBe->apTemp[i];
|
return pBe->apTemp[i];
|
||||||
|
10
src/dbbe.h
10
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.2 2000/05/31 02:27:49 drh Exp $
|
** $Id: dbbe.h,v 1.3 2000/05/31 20:00:52 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE_DBBE_H_
|
#ifndef _SQLITE_DBBE_H_
|
||||||
#define _SQLITE_DBBE_H_
|
#define _SQLITE_DBBE_H_
|
||||||
@@ -59,6 +59,9 @@ void sqliteDbbeClose(Dbbe*);
|
|||||||
|
|
||||||
/* Open a particular table of a previously opened database.
|
/* Open a particular table of a previously opened database.
|
||||||
** Create the table if it doesn't already exist and writeable!=0.
|
** Create the table if it doesn't already exist and writeable!=0.
|
||||||
|
**
|
||||||
|
** If zTableName is 0 or "", then a temporary table is created that
|
||||||
|
** will be deleted when closed.
|
||||||
*/
|
*/
|
||||||
DbbeTable *sqliteDbbeOpenTable(Dbbe*, const char *zTableName, int writeable);
|
DbbeTable *sqliteDbbeOpenTable(Dbbe*, const char *zTableName, int writeable);
|
||||||
|
|
||||||
@@ -76,6 +79,11 @@ void sqliteDbbeCloseTable(DbbeTable*);
|
|||||||
*/
|
*/
|
||||||
int sqliteDbbeFetch(DbbeTable*, int nKey, char *pKey);
|
int sqliteDbbeFetch(DbbeTable*, int nKey, char *pKey);
|
||||||
|
|
||||||
|
/* Return 1 if the given key is already in the table. Return 0
|
||||||
|
** if it is not.
|
||||||
|
*/
|
||||||
|
int sqliteDbbeTest(DbbeTable*, int nKey, char *pKey);
|
||||||
|
|
||||||
/* Retrieve the key or data used for the last fetch. Only size
|
/* Retrieve the key or data used for the last fetch. Only size
|
||||||
** bytes are read beginning with the offset-th byte. The return
|
** bytes are read beginning with the offset-th byte. The return
|
||||||
** value is the actual number of bytes read.
|
** value is the actual number of bytes read.
|
||||||
|
15
src/parse.y
15
src/parse.y
@@ -26,7 +26,7 @@
|
|||||||
** the parser. Lemon will also generate a header file containing
|
** the parser. Lemon will also generate a header file containing
|
||||||
** numeric codes for all of the tokens.
|
** numeric codes for all of the tokens.
|
||||||
**
|
**
|
||||||
** @(#) $Id: parse.y,v 1.5 2000/05/31 18:20:14 drh Exp $
|
** @(#) $Id: parse.y,v 1.6 2000/05/31 20:00:52 drh Exp $
|
||||||
*/
|
*/
|
||||||
%token_prefix TK_
|
%token_prefix TK_
|
||||||
%token_type {Token}
|
%token_type {Token}
|
||||||
@@ -125,10 +125,15 @@ cmd ::= DROP TABLE id(X). {sqliteDropTable(pParse,&X);}
|
|||||||
// The select statement
|
// The select statement
|
||||||
//
|
//
|
||||||
cmd ::= select.
|
cmd ::= select.
|
||||||
select ::= SELECT selcollist(W) from(X) where_opt(Y) orderby_opt(Z).
|
select ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) orderby_opt(Z).
|
||||||
{sqliteSelect(pParse, W, X, Y, Z);}
|
{sqliteSelect(pParse, W, X, Y, Z, D);}
|
||||||
select ::= SELECT STAR from(X) where_opt(Y) orderby_opt(Z).
|
select ::= SELECT distinct(D) STAR from(X) where_opt(Y) orderby_opt(Z).
|
||||||
{sqliteSelect(pParse, 0, X, Y, Z);}
|
{sqliteSelect(pParse, 0, X, Y, Z, D);}
|
||||||
|
|
||||||
|
%type distinct {int}
|
||||||
|
|
||||||
|
distinct(A) ::= DISTINCT. {A = 1;}
|
||||||
|
distinct(A) ::= . {A = 0;}
|
||||||
|
|
||||||
%type selcollist {ExprList*}
|
%type selcollist {ExprList*}
|
||||||
%destructor selcollist {sqliteExprListDelete($$);}
|
%destructor selcollist {sqliteExprListDelete($$);}
|
||||||
|
28
src/select.c
28
src/select.c
@@ -24,7 +24,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements.
|
** to handle SELECT statements.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.2 2000/05/31 18:20:14 drh Exp $
|
** $Id: select.c,v 1.3 2000/05/31 20:00:52 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -37,7 +37,8 @@ void sqliteSelect(
|
|||||||
ExprList *pEList, /* List of fields to extract. NULL means "*" */
|
ExprList *pEList, /* List of fields to extract. NULL means "*" */
|
||||||
IdList *pTabList, /* List of tables to select from */
|
IdList *pTabList, /* List of tables to select from */
|
||||||
Expr *pWhere, /* The WHERE clause. May be NULL */
|
Expr *pWhere, /* The WHERE clause. May be NULL */
|
||||||
ExprList *pOrderBy /* The ORDER BY clause. May be NULL */
|
ExprList *pOrderBy, /* The ORDER BY clause. May be NULL */
|
||||||
|
int distinct /* If true, only output distinct results */
|
||||||
){
|
){
|
||||||
int i, j;
|
int i, j;
|
||||||
WhereInfo *pWInfo;
|
WhereInfo *pWInfo;
|
||||||
@@ -121,6 +122,12 @@ void sqliteSelect(
|
|||||||
pOrderBy = 0;
|
pOrderBy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Turn off distinct if this is an aggregate
|
||||||
|
*/
|
||||||
|
if( isAgg ){
|
||||||
|
distinct = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Begin generating code.
|
/* Begin generating code.
|
||||||
*/
|
*/
|
||||||
v = pParse->pVdbe;
|
v = pParse->pVdbe;
|
||||||
@@ -189,6 +196,10 @@ void sqliteSelect(
|
|||||||
|
|
||||||
/* Begin the database scan
|
/* Begin the database scan
|
||||||
*/
|
*/
|
||||||
|
if( distinct ){
|
||||||
|
distinct = pTabList->nId*2+1;
|
||||||
|
sqliteVdbeAddOp(v, OP_Open, distinct, 0, 0, 0);
|
||||||
|
}
|
||||||
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0);
|
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0);
|
||||||
if( pWInfo==0 ) goto select_cleanup;
|
if( pWInfo==0 ) goto select_cleanup;
|
||||||
|
|
||||||
@@ -200,6 +211,19 @@ void sqliteSelect(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the current result is not distinct, script the remainder
|
||||||
|
** of this processing.
|
||||||
|
*/
|
||||||
|
if( distinct ){
|
||||||
|
int isDistinct = sqliteVdbeMakeLabel(v);
|
||||||
|
sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1, 0, 0);
|
||||||
|
sqliteVdbeAddOp(v, OP_Distinct, distinct, isDistinct, 0, 0);
|
||||||
|
sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0, 0, 0);
|
||||||
|
sqliteVdbeAddOp(v, OP_Goto, 0, pWInfo->iContinue, 0, 0);
|
||||||
|
sqliteVdbeAddOp(v, OP_String, 0, 0, "", isDistinct);
|
||||||
|
sqliteVdbeAddOp(v, OP_Put, distinct, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* If there is no ORDER BY clause, then we can invoke the callback
|
/* If there is no ORDER BY clause, then we can invoke the callback
|
||||||
** right away. If there is an ORDER BY, then we need to put the
|
** right away. If there is an ORDER BY, then we need to put the
|
||||||
** data into an appropriate sorter record.
|
** data into an appropriate sorter record.
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.5 2000/05/31 15:34:53 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.6 2000/05/31 20:00:52 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqlite.h"
|
#include "sqlite.h"
|
||||||
#include "dbbe.h"
|
#include "dbbe.h"
|
||||||
@@ -249,7 +249,7 @@ void sqliteIdListAddAlias(IdList*, Token*);
|
|||||||
void sqliteIdListDelete(IdList*);
|
void sqliteIdListDelete(IdList*);
|
||||||
void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, Token*, Token*);
|
void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, Token*, Token*);
|
||||||
void sqliteDropIndex(Parse*, Token*);
|
void sqliteDropIndex(Parse*, Token*);
|
||||||
void sqliteSelect(Parse*, ExprList*, IdList*, Expr*, ExprList*);
|
void sqliteSelect(Parse*, ExprList*, IdList*, Expr*, ExprList*, int);
|
||||||
void sqliteDeleteFrom(Parse*, Token*, Expr*);
|
void sqliteDeleteFrom(Parse*, Token*, Expr*);
|
||||||
void sqliteUpdate(Parse*, Token*, ExprList*, Expr*);
|
void sqliteUpdate(Parse*, Token*, ExprList*, Expr*);
|
||||||
WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int);
|
WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int);
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
** individual tokens and sends those tokens one-by-one over to the
|
** individual tokens and sends those tokens one-by-one over to the
|
||||||
** parser for analysis.
|
** parser for analysis.
|
||||||
**
|
**
|
||||||
** $Id: tokenize.c,v 1.4 2000/05/31 02:27:49 drh Exp $
|
** $Id: tokenize.c,v 1.5 2000/05/31 20:00:53 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -61,6 +61,7 @@ static Keyword aKeywordTable[] = {
|
|||||||
{ "DELETE", 0, TK_DELETE, 0 },
|
{ "DELETE", 0, TK_DELETE, 0 },
|
||||||
{ "DELIMITERS", 0, TK_DELIMITERS, 0 },
|
{ "DELIMITERS", 0, TK_DELIMITERS, 0 },
|
||||||
{ "DESC", 0, TK_DESC, 0 },
|
{ "DESC", 0, TK_DESC, 0 },
|
||||||
|
{ "DISTINCT", 0, TK_DISTINCT, 0 },
|
||||||
{ "DROP", 0, TK_DROP, 0 },
|
{ "DROP", 0, TK_DROP, 0 },
|
||||||
{ "EXPLAIN", 0, TK_EXPLAIN, 0 },
|
{ "EXPLAIN", 0, TK_EXPLAIN, 0 },
|
||||||
{ "FROM", 0, TK_FROM, 0 },
|
{ "FROM", 0, TK_FROM, 0 },
|
||||||
|
77
src/vdbe.c
77
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.4 2000/05/31 15:34:53 drh Exp $
|
** $Id: vdbe.c,v 1.5 2000/05/31 20:00:53 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -392,23 +392,23 @@ void sqliteVdbeDelete(Vdbe *p){
|
|||||||
*/
|
*/
|
||||||
static char *zOpName[] = { 0,
|
static char *zOpName[] = { 0,
|
||||||
"Open", "Close", "Fetch", "New",
|
"Open", "Close", "Fetch", "New",
|
||||||
"Put", "Delete", "Field", "Key",
|
"Put", "Distinct", "Delete", "Field",
|
||||||
"Rewind", "Next", "Destroy", "Reorganize",
|
"Key", "Rewind", "Next", "Destroy",
|
||||||
"ResetIdx", "NextIdx", "PutIdx", "DeleteIdx",
|
"Reorganize", "ResetIdx", "NextIdx", "PutIdx",
|
||||||
"ListOpen", "ListWrite", "ListRewind", "ListRead",
|
"DeleteIdx", "ListOpen", "ListWrite", "ListRewind",
|
||||||
"ListClose", "SortOpen", "SortPut", "SortMakeRec",
|
"ListRead", "ListClose", "SortOpen", "SortPut",
|
||||||
"SortMakeKey", "Sort", "SortNext", "SortKey",
|
"SortMakeRec", "SortMakeKey", "Sort", "SortNext",
|
||||||
"SortCallback", "SortClose", "FileOpen", "FileRead",
|
"SortKey", "SortCallback", "SortClose", "FileOpen",
|
||||||
"FileField", "FileClose", "MakeRecord", "MakeKey",
|
"FileRead", "FileField", "FileClose", "MakeRecord",
|
||||||
"Goto", "If", "Halt", "ColumnCount",
|
"MakeKey", "Goto", "If", "Halt",
|
||||||
"ColumnName", "Callback", "Integer", "String",
|
"ColumnCount", "ColumnName", "Callback", "Integer",
|
||||||
"Pop", "Dup", "Pull", "Add",
|
"String", "Pop", "Dup", "Pull",
|
||||||
"AddImm", "Subtract", "Multiply", "Divide",
|
"Add", "AddImm", "Subtract", "Multiply",
|
||||||
"Min", "Max", "Like", "Glob",
|
"Divide", "Min", "Max", "Like",
|
||||||
"Eq", "Ne", "Lt", "Le",
|
"Glob", "Eq", "Ne", "Lt",
|
||||||
"Gt", "Ge", "IsNull", "NotNull",
|
"Le", "Gt", "Ge", "IsNull",
|
||||||
"Negative", "And", "Or", "Not",
|
"NotNull", "Negative", "And", "Or",
|
||||||
"Concat", "Noop",
|
"Not", "Concat", "Noop",
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1247,7 +1247,7 @@ int sqliteVdbeExec(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: MakeKey P1 * *
|
/* Opcode: MakeKey P1 P2 *
|
||||||
**
|
**
|
||||||
** Convert the top P1 entries of the stack into a single entry suitable
|
** Convert the top P1 entries of the stack into a single entry suitable
|
||||||
** for use as the key in an index or a sort. The top P1 records are
|
** for use as the key in an index or a sort. The top P1 records are
|
||||||
@@ -1256,6 +1256,11 @@ int sqliteVdbeExec(
|
|||||||
** lowest entry in the stack is the first field and the top of the
|
** lowest entry in the stack is the first field and the top of the
|
||||||
** stack becomes the last.
|
** stack becomes the last.
|
||||||
**
|
**
|
||||||
|
** If P2 is not zero, then the original entries remain on the stack
|
||||||
|
** and the new key is pushed on top. If P2 is zero, the original
|
||||||
|
** data is popped off the stack first then the new key is pushed
|
||||||
|
** back in its place.
|
||||||
|
**
|
||||||
** See also the SortMakeKey opcode.
|
** See also the SortMakeKey opcode.
|
||||||
*/
|
*/
|
||||||
case OP_MakeKey: {
|
case OP_MakeKey: {
|
||||||
@@ -1280,7 +1285,7 @@ int sqliteVdbeExec(
|
|||||||
if( i<p->tos ) zNewKey[j++] = '\t';
|
if( i<p->tos ) zNewKey[j++] = '\t';
|
||||||
}
|
}
|
||||||
zNewKey[j] = 0;
|
zNewKey[j] = 0;
|
||||||
PopStack(p, nField);
|
if( pOp->p2==0 ) PopStack(p, nField);
|
||||||
NeedStack(p, p->tos+1);
|
NeedStack(p, p->tos+1);
|
||||||
p->tos++;
|
p->tos++;
|
||||||
p->iStack[p->tos] = nByte;
|
p->iStack[p->tos] = nByte;
|
||||||
@@ -1353,6 +1358,38 @@ int sqliteVdbeExec(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Opcode: Distinct P1 P2 *
|
||||||
|
**
|
||||||
|
** Use the top of the stack as a key. If a record with that key
|
||||||
|
** does not exist in table P1, then jump to P2. If the record
|
||||||
|
** does already exist, then fall thru. The record is not retrieved.
|
||||||
|
** The key is not popped from the stack.
|
||||||
|
*/
|
||||||
|
case OP_Distinct: {
|
||||||
|
int i = pOp->p1;
|
||||||
|
int tos = p->tos;
|
||||||
|
int alreadyExists = 0;
|
||||||
|
if( tos<0 ) goto not_enough_stack;
|
||||||
|
if( i>=0 && i<p->nTable && p->aTab[i].pTable ){
|
||||||
|
if( p->zStack[tos]==0 ){
|
||||||
|
alreadyExists = sqliteDbbeTest(p->aTab[i].pTable, sizeof(int),
|
||||||
|
(char*)&p->iStack[tos]);
|
||||||
|
}else{
|
||||||
|
alreadyExists = sqliteDbbeTest(p->aTab[i].pTable, p->iStack[tos],
|
||||||
|
p->zStack[tos]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( !alreadyExists ){
|
||||||
|
pc = pOp->p2;
|
||||||
|
if( pc<0 || pc>p->nOp ){
|
||||||
|
sqliteSetString(pzErrMsg, "jump destination out of range", 0);
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
pc--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Opcode: New P1 * *
|
/* Opcode: New P1 * *
|
||||||
**
|
**
|
||||||
** Get a new integer key not previous used by table P1 and
|
** Get a new integer key not previous used by table P1 and
|
||||||
|
135
src/vdbe.h
135
src/vdbe.h
@@ -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.3 2000/05/31 02:27:50 drh Exp $
|
** $Id: vdbe.h,v 1.4 2000/05/31 20:00:53 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE_VDBE_H_
|
#ifndef _SQLITE_VDBE_H_
|
||||||
#define _SQLITE_VDBE_H_
|
#define _SQLITE_VDBE_H_
|
||||||
@@ -76,83 +76,84 @@ typedef struct VdbeOp VdbeOp;
|
|||||||
#define OP_Fetch 3
|
#define OP_Fetch 3
|
||||||
#define OP_New 4
|
#define OP_New 4
|
||||||
#define OP_Put 5
|
#define OP_Put 5
|
||||||
#define OP_Delete 6
|
#define OP_Distinct 6
|
||||||
#define OP_Field 7
|
#define OP_Delete 7
|
||||||
#define OP_Key 8
|
#define OP_Field 8
|
||||||
#define OP_Rewind 9
|
#define OP_Key 9
|
||||||
#define OP_Next 10
|
#define OP_Rewind 10
|
||||||
|
#define OP_Next 11
|
||||||
|
|
||||||
#define OP_Destroy 11
|
#define OP_Destroy 12
|
||||||
#define OP_Reorganize 12
|
#define OP_Reorganize 13
|
||||||
|
|
||||||
#define OP_ResetIdx 13
|
#define OP_ResetIdx 14
|
||||||
#define OP_NextIdx 14
|
#define OP_NextIdx 15
|
||||||
#define OP_PutIdx 15
|
#define OP_PutIdx 16
|
||||||
#define OP_DeleteIdx 16
|
#define OP_DeleteIdx 17
|
||||||
|
|
||||||
#define OP_ListOpen 17
|
#define OP_ListOpen 18
|
||||||
#define OP_ListWrite 18
|
#define OP_ListWrite 19
|
||||||
#define OP_ListRewind 19
|
#define OP_ListRewind 20
|
||||||
#define OP_ListRead 20
|
#define OP_ListRead 21
|
||||||
#define OP_ListClose 21
|
#define OP_ListClose 22
|
||||||
|
|
||||||
#define OP_SortOpen 22
|
#define OP_SortOpen 23
|
||||||
#define OP_SortPut 23
|
#define OP_SortPut 24
|
||||||
#define OP_SortMakeRec 24
|
#define OP_SortMakeRec 25
|
||||||
#define OP_SortMakeKey 25
|
#define OP_SortMakeKey 26
|
||||||
#define OP_Sort 26
|
#define OP_Sort 27
|
||||||
#define OP_SortNext 27
|
#define OP_SortNext 28
|
||||||
#define OP_SortKey 28
|
#define OP_SortKey 29
|
||||||
#define OP_SortCallback 29
|
#define OP_SortCallback 30
|
||||||
#define OP_SortClose 30
|
#define OP_SortClose 31
|
||||||
|
|
||||||
#define OP_FileOpen 31
|
#define OP_FileOpen 32
|
||||||
#define OP_FileRead 32
|
#define OP_FileRead 33
|
||||||
#define OP_FileField 33
|
#define OP_FileField 34
|
||||||
#define OP_FileClose 34
|
#define OP_FileClose 35
|
||||||
|
|
||||||
#define OP_MakeRecord 35
|
#define OP_MakeRecord 36
|
||||||
#define OP_MakeKey 36
|
#define OP_MakeKey 37
|
||||||
|
|
||||||
#define OP_Goto 37
|
#define OP_Goto 38
|
||||||
#define OP_If 38
|
#define OP_If 39
|
||||||
#define OP_Halt 39
|
#define OP_Halt 40
|
||||||
|
|
||||||
#define OP_ColumnCount 40
|
#define OP_ColumnCount 41
|
||||||
#define OP_ColumnName 41
|
#define OP_ColumnName 42
|
||||||
#define OP_Callback 42
|
#define OP_Callback 43
|
||||||
|
|
||||||
#define OP_Integer 43
|
#define OP_Integer 44
|
||||||
#define OP_String 44
|
#define OP_String 45
|
||||||
#define OP_Pop 45
|
#define OP_Pop 46
|
||||||
#define OP_Dup 46
|
#define OP_Dup 47
|
||||||
#define OP_Pull 47
|
#define OP_Pull 48
|
||||||
|
|
||||||
#define OP_Add 48
|
#define OP_Add 49
|
||||||
#define OP_AddImm 49
|
#define OP_AddImm 50
|
||||||
#define OP_Subtract 50
|
#define OP_Subtract 51
|
||||||
#define OP_Multiply 51
|
#define OP_Multiply 52
|
||||||
#define OP_Divide 52
|
#define OP_Divide 53
|
||||||
#define OP_Min 53
|
#define OP_Min 54
|
||||||
#define OP_Max 54
|
#define OP_Max 55
|
||||||
#define OP_Like 55
|
#define OP_Like 56
|
||||||
#define OP_Glob 56
|
#define OP_Glob 57
|
||||||
#define OP_Eq 57
|
#define OP_Eq 58
|
||||||
#define OP_Ne 58
|
#define OP_Ne 59
|
||||||
#define OP_Lt 59
|
#define OP_Lt 60
|
||||||
#define OP_Le 60
|
#define OP_Le 61
|
||||||
#define OP_Gt 61
|
#define OP_Gt 62
|
||||||
#define OP_Ge 62
|
#define OP_Ge 63
|
||||||
#define OP_IsNull 63
|
#define OP_IsNull 64
|
||||||
#define OP_NotNull 64
|
#define OP_NotNull 65
|
||||||
#define OP_Negative 65
|
#define OP_Negative 66
|
||||||
#define OP_And 66
|
#define OP_And 67
|
||||||
#define OP_Or 67
|
#define OP_Or 68
|
||||||
#define OP_Not 68
|
#define OP_Not 69
|
||||||
#define OP_Concat 69
|
#define OP_Concat 70
|
||||||
#define OP_Noop 70
|
#define OP_Noop 71
|
||||||
|
|
||||||
#define OP_MAX 70
|
#define OP_MAX 71
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Prototypes for the VDBE interface. See comments on the implementation
|
** Prototypes for the VDBE interface. See comments on the implementation
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Run this TCL script to generate HTML for the index.html file.
|
# Run this TCL script to generate HTML for the index.html file.
|
||||||
#
|
#
|
||||||
set rcsid {$Id: index.tcl,v 1.6 2000/05/31 15:34:54 drh Exp $}
|
set rcsid {$Id: index.tcl,v 1.7 2000/05/31 20:00:53 drh Exp $}
|
||||||
|
|
||||||
puts {<html>
|
puts {<html>
|
||||||
<head><title>SQLite: An SQL Frontend For GDBM</title></head>
|
<head><title>SQLite: An SQL Frontend For GDBM</title></head>
|
||||||
@@ -119,6 +119,9 @@ puts {<h2>Related Sites</h2>
|
|||||||
about the Berkeley DB library, see
|
about the Berkeley DB library, see
|
||||||
<a href="http://www.sleepcat.com/">http://www.sleepycat.com</a>
|
<a href="http://www.sleepcat.com/">http://www.sleepycat.com</a>
|
||||||
</p></li>
|
</p></li>
|
||||||
|
|
||||||
|
<li><p>Here is a <a href="http://w3.one.net/~jhoffman/sqltut.htm">
|
||||||
|
tutorial on SQL</a>.</p></li>
|
||||||
</ul>}
|
</ul>}
|
||||||
|
|
||||||
puts {
|
puts {
|
||||||
|
Reference in New Issue
Block a user