From dce2cbe65f9bedf260d320c775d59727a6ddb9bb Mon Sep 17 00:00:00 2001
From: drh
Date: Wed, 31 May 2000 02:27:49 +0000
Subject: [PATCH] :-) (CVS 20)
FossilOrigin-Name: 01d85b35e9c4ca5619ad21a4232a8f8bf9ec3538
---
Makefile.in | 4 ++
manifest | 39 +++++++-------
manifest.uuid | 2 +-
src/build.c | 45 +++++++++++++++-
src/dbbe.c | 18 ++++++-
src/dbbe.h | 5 +-
src/parse.y | 11 ++--
src/shell.c | 6 +--
src/sqliteInt.h | 5 +-
src/tokenize.c | 5 +-
src/util.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++-
src/vdbe.c | 107 ++++++++++++++++++++++++++++++-------
src/vdbe.h | 139 +++++++++++++++++++++++++-----------------------
src/where.c | 47 ++++++++++++----
www/changes.tcl | 46 ++++++++++++++++
www/index.tcl | 6 ++-
www/sqlite.tcl | 14 ++++-
17 files changed, 505 insertions(+), 131 deletions(-)
create mode 100644 www/changes.tcl
diff --git a/Makefile.in b/Makefile.in
index ab446b1be4..8c277993d1 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -145,6 +145,9 @@ sqlite.html: $(TOP)/www/sqlite.tcl
c_interface.html: $(TOP)/www/c_interface.tcl
tclsh $(TOP)/www/c_interface.tcl >c_interface.html
+changes.html: $(TOP)/www/changes.tcl
+ tclsh $(TOP)/www/changes.tcl >changes.html
+
# Files to be published on the website.
#
PUBLISH = \
@@ -152,6 +155,7 @@ PUBLISH = \
all.tar.gz \
index.html \
sqlite.html \
+ changes.html \
c_interface.html
website: $(PUBLISH)
diff --git a/manifest b/manifest
index f65555fb14..e1a4a8ad4b 100644
--- a/manifest
+++ b/manifest
@@ -1,25 +1,25 @@
-C :-)\s(CVS\s19)
-D 2000-05-30T20:17:49
+C :-)\s(CVS\s20)
+D 2000-05-31T02:27:49
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
-F Makefile.in 89921c1ee4de75275bfadfbac198396da31704d1
+F Makefile.in dd79c78825935c5711ce45c372b0ac0f194b6d43
F README 6b5960603c7f8bf42fc022b4b6436f242f238dbb
F configure 00a5b5c82147a576fa6e82d7c1b0d55c321d6d2c x
F configure.in 6ccfd5fc80517f7cfe605a7fc7e0f62d962a233c
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
-F src/build.c 335df4b65f49d335438d3a0cd7e48d19713a1917
-F src/dbbe.c 159c39f8bf5475c34904786fad4f3f0f579d9eb6
-F src/dbbe.h bedeb3a0985bb584458e7849fb59927e99e751e6
+F src/build.c c6b500077913cde55871d1f9c0d17d4ee4a86828
+F src/dbbe.c dc9439f839d13e633158808e352056b531f17e1b
+F src/dbbe.h b678e31c32fa252e6fba830ad16ed8978d1521a9
F src/main.c 25cce7bce0eb3ba10bada7c05f4b38dc6dbbc86f
-F src/parse.y 50ca06d471132e16bb47c56f19553e4efd5b3d4a
-F src/shell.c 3ffa9059514cd4db3bd64e0797bf7ebbe1ea8ee3
+F src/parse.y 05de7dec046dd8bd11f8cc3513ff8b27624618c8
+F src/shell.c c5752d32cdeaa7d548d4f91177b697b023a00381
F src/sqlite.h 2397c17a8f4ca90c09acab0100dc7e2f8f441b69
-F src/sqliteInt.h 749da8b3e4ce146fd172aeb59b6db04c57726d7a
+F src/sqliteInt.h 9ac3f9e05bbc5913531473c86d4742343ae670c5
F src/tclsqlite.c 9efd29f79ded6a900aa3d142169c8bfe03b7affd
-F src/tokenize.c e176b2c1c38e11482ee3419d6b50b733860a1587
-F src/util.c 2a0314dcc9de230526380765339071a5b304d70d
-F src/vdbe.c 117ce5541143e3af9dccdc15c22c4920a7b9bdb4
-F src/vdbe.h 03de26632f2e608c2a44a40262fbba21a8bdfd81
-F src/where.c 2c8de69c4cf5a620ed380d3d6bb658bbbe8da5d5
+F src/tokenize.c 5b066f314646d6c5396a253315e5e95d107e1800
+F src/util.c 6b4327d7fbf684f8635155d4acb847ae991b3ebc
+F src/vdbe.c 74ff55bc2910e25bd811638233f6c02fb1a17fbc
+F src/vdbe.h 02b470d344caed04451c896be7a775068dbdf076
+F src/where.c fd9faea693083c1bde83f824b98f7eb81c4762cc
F test/all.test 66a8a5b8291a472157944edcdce51a320ebd1f35
F test/copy.test 641bd3cfaab61c4ee32889587e21e4c70788a97a
F test/delete.test 814d53e3b0d2d7069fb17e005d4041454d6585d4
@@ -36,9 +36,10 @@ F tool/opNames.awk 2bd9071a138e4e2be13dc98fe066398a61219e1e
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/renumberOps.awk 6d067177ad5f8d711b79577b462da9b3634bd0a9
F www/c_interface.tcl f875864edf7974157d1c257ca08de854660882a5
-F www/index.tcl 2466d1b2e26c6f354b0acedee12025309a216799
-F www/sqlite.tcl 947e067bcc347dc767af4c1a6e5a8d47d8404aa3
-P 2d41caec807a6ab83b67e59c849ebbda004f2869
-R d274f71e9bf0807a8f2c186fb0e9f965
+F www/changes.tcl 38ff869ccbf99388d53abd08aeea4e24e2bb23b7
+F www/index.tcl 57a97afafe04ab53d1996ba3a61ac41fa8453f5a
+F www/sqlite.tcl 7deb564df188ad4523adecfe2365de6d09f6dfd9
+P 03725ce5ae871247789ece0f2c3426f74ba575e7
+R bab7f299b23f92a0096c17a89a463018
U drh
-Z 1247bb7c9fa8cc79296726f95e563a76
+Z e30b944ebaee88defeb667112902d5c8
diff --git a/manifest.uuid b/manifest.uuid
index e900404329..1b7f2dfd75 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-03725ce5ae871247789ece0f2c3426f74ba575e7
\ No newline at end of file
+01d85b35e9c4ca5619ad21a4232a8f8bf9ec3538
\ No newline at end of file
diff --git a/src/build.c b/src/build.c
index 4b29cc187e..fd0aaeef31 100644
--- a/src/build.c
+++ b/src/build.c
@@ -24,7 +24,7 @@
** This file contains C code routines that are called by the parser
** when syntax rules are reduced.
**
-** $Id: build.c,v 1.9 2000/05/30 19:22:26 drh Exp $
+** $Id: build.c,v 1.10 2000/05/31 02:27:49 drh Exp $
*/
#include "sqliteInt.h"
@@ -1528,3 +1528,46 @@ void sqliteCopy(
copy_cleanup:
return;
}
+
+/*
+** The non-standard VACUUM command is used to clean up the database,
+** collapse free space, etc. It is modelled after the VACUUM command
+** in PostgreSQL.
+*/
+void sqliteVacuum(Parse *pParse, Token *pTableName){
+ char *zName;
+ Vdbe *v;
+
+ if( pTableName ){
+ zName = sqliteTableNameFromToken(pTableName);
+ }else{
+ zName = 0;
+ }
+ if( zName && sqliteFindIndex(pParse->db, zName)==0
+ && sqliteFindTable(pParse->db, zName)==0 ){
+ sqliteSetString(&pParse->zErrMsg, "no such table or index: ", zName, 0);
+ pParse->nErr++;
+ goto vacuum_cleanup;
+ }
+ v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
+ if( v==0 ) goto vacuum_cleanup;
+ if( zName ){
+ sqliteVdbeAddOp(v, OP_Reorganize, 0, 0, zName, 0);
+ }else{
+ int h;
+ Table *pTab;
+ Index *pIdx;
+ for(h=0; hdb->apTblHash[h]; pTab; pTab=pTab->pHash){
+ sqliteVdbeAddOp(v, OP_Reorganize, 0, 0, pTab->zName, 0);
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ sqliteVdbeAddOp(v, OP_Reorganize, 0, 0, pIdx->zName, 0);
+ }
+ }
+ }
+ }
+
+vacuum_cleanup:
+ sqliteFree(zName);
+ return;
+}
diff --git a/src/dbbe.c b/src/dbbe.c
index 51cf86b0b9..0e96bf85e6 100644
--- a/src/dbbe.c
+++ b/src/dbbe.c
@@ -30,7 +30,7 @@
** relatively simple to convert to a different database such
** as NDBM, SDBM, or BerkeleyDB.
**
-** $Id: dbbe.c,v 1.2 2000/05/30 18:45:24 drh Exp $
+** $Id: dbbe.c,v 1.3 2000/05/31 02:27:49 drh Exp $
*/
#include "sqliteInt.h"
#include
@@ -199,6 +199,22 @@ void sqliteDbbeDropTable(Dbbe *pBe, const char *zTable){
sqliteFree(zFile);
}
+/*
+** Reorganize a table to reduce search times and disk usage.
+*/
+void sqliteDbbeReorganizeTable(Dbbe *pBe, const char *zTable){
+ char *zFile; /* Name of the table file */
+ DbbeTable *pTab;
+
+ pTab = sqliteDbbeOpenTable(pBe, zTable, 1);
+ if( pTab && pTab->pFile && pTab->pFile->dbf ){
+ gdbm_reorganize(pTab->pFile->dbf);
+ }
+ if( pTab ){
+ sqliteDbbeCloseTable(pTab);
+ }
+}
+
/*
** Close a table previously opened by sqliteDbbeOpenTable().
*/
diff --git a/src/dbbe.h b/src/dbbe.h
index 26e83a6485..c9f424d498 100644
--- a/src/dbbe.h
+++ b/src/dbbe.h
@@ -28,7 +28,7 @@
** This library was originally designed to support the following
** backends: GDBM, NDBM, SDBM, Berkeley DB.
**
-** $Id: dbbe.h,v 1.1 2000/05/29 14:26:01 drh Exp $
+** $Id: dbbe.h,v 1.2 2000/05/31 02:27:49 drh Exp $
*/
#ifndef _SQLITE_DBBE_H_
#define _SQLITE_DBBE_H_
@@ -65,6 +65,9 @@ DbbeTable *sqliteDbbeOpenTable(Dbbe*, const char *zTableName, int writeable);
/* Delete a table from the database */
void sqliteDbbeDropTable(Dbbe*, const char *zTableName);
+/* Reorganize a table to speed access or reduce its disk usage */
+void sqliteDbbeReorganizeTable(Dbbe*, const char *zTableName);
+
/* Close a table */
void sqliteDbbeCloseTable(DbbeTable*);
diff --git a/src/parse.y b/src/parse.y
index 7b58846e61..89d003575c 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -26,7 +26,7 @@
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.2 2000/05/30 16:27:04 drh Exp $
+** @(#) $Id: parse.y,v 1.3 2000/05/31 02:27:49 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@@ -236,7 +236,7 @@ fieldlist(A) ::= ID(Y). {A = sqliteIdListAppend(0,&Y);}
%left OR.
%left AND.
-%left EQ NE ISNULL NOTNULL IS.
+%left EQ NE ISNULL NOTNULL IS LIKE GLOB.
%left GT GE LT LE.
%left PLUS MINUS.
%left STAR SLASH PERCENT.
@@ -264,7 +264,9 @@ expr(A) ::= expr(X) LE expr(Y). {A = sqliteExpr(TK_LE, X, Y, 0);}
expr(A) ::= expr(X) GE expr(Y). {A = sqliteExpr(TK_GE, X, Y, 0);}
expr(A) ::= expr(X) NE expr(Y). {A = sqliteExpr(TK_NE, X, Y, 0);}
expr(A) ::= expr(X) EQ expr(Y). {A = sqliteExpr(TK_EQ, X, Y, 0);}
-expr(A) ::= expr(X) IS expr(Y). {A = sqliteExpr(TK_EQ, X, Y, 0);}
+expr(A) ::= expr(X) LIKE expr(Y). {A = sqliteExpr(TK_LIKE, X, Y, 0);}
+expr(A) ::= expr(X) GLOB expr(Y). {A = sqliteExpr(TK_GLOB,X,Y,0);}
+// expr(A) ::= expr(X) IS expr(Y). {A = sqliteExpr(TK_EQ, X, Y, 0);}
expr(A) ::= expr(X) PLUS expr(Y). {A = sqliteExpr(TK_PLUS, X, Y, 0);}
expr(A) ::= expr(X) MINUS expr(Y). {A = sqliteExpr(TK_MINUS, X, Y, 0);}
expr(A) ::= expr(X) STAR expr(Y). {A = sqliteExpr(TK_STAR, X, Y, 0);}
@@ -309,3 +311,6 @@ cmd ::= COPY id(X) FROM id(Y) USING DELIMITERS STRING(Z).
{sqliteCopy(pParse,&X,&Y,&Z);}
cmd ::= COPY id(X) FROM id(Y).
{sqliteCopy(pParse,&X,&Y,0);}
+
+cmd ::= VACUUM. {sqliteVacuum(pParse,0);}
+cmd ::= VACUUM id(X). {sqliteVacuum(pParse,&X);}
diff --git a/src/shell.c b/src/shell.c
index b044ad46ea..4cc8a3032d 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -24,7 +24,7 @@
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
-** $Id: shell.c,v 1.3 2000/05/30 18:45:24 drh Exp $
+** $Id: shell.c,v 1.4 2000/05/31 02:27:49 drh Exp $
*/
#include
#include
@@ -300,7 +300,7 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
data.showHeader = 0;
data.mode = MODE_List;
sprintf(zSql, "SELECT name FROM sqlite_master "
- "WHERE type='index' AND tbl_name='%.00s' "
+ "WHERE type='index' AND tbl_name LIKE '%.00s' "
"ORDER BY name", azArg[1]);
sqlite_exec(db, zSql, callback, &data, &zErrMsg);
if( zErrMsg ){
@@ -343,7 +343,7 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
data.showHeader = 0;
data.mode = MODE_List;
if( nArg>1 ){
- sprintf(zSql, "SELECT sql FROM sqlite_master WHERE name='%.900s'",
+ sprintf(zSql, "SELECT sql FROM sqlite_master WHERE name LIKE '%.900s'",
azArg[1]);
}else{
sprintf(zSql, "SELECT sql FROM sqlite_master "
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 7bbabff159..c64a147379 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -23,7 +23,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.3 2000/05/30 16:27:04 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.4 2000/05/31 02:27:49 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
@@ -248,3 +248,6 @@ void sqliteExprIfTrue(Parse*, Expr*, int);
void sqliteExprIfFalse(Parse*, Expr*, int);
Table *sqliteFindTable(sqlite*,char*);
void sqliteCopy(Parse*, Token*, Token*, Token*);
+void sqliteVacuum(Parse*, Token*);
+int sqliteGlobCompare(const char*,const char*);
+int sqliteLikeCompare(const unsigned char*,const unsigned char*);
diff --git a/src/tokenize.c b/src/tokenize.c
index ac062d0b55..d47476ff7b 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -27,7 +27,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.3 2000/05/30 16:27:04 drh Exp $
+** $Id: tokenize.c,v 1.4 2000/05/31 02:27:49 drh Exp $
*/
#include "sqliteInt.h"
#include
@@ -64,12 +64,14 @@ static Keyword aKeywordTable[] = {
{ "DROP", 0, TK_DROP, 0 },
{ "EXPLAIN", 0, TK_EXPLAIN, 0 },
{ "FROM", 0, TK_FROM, 0 },
+ { "GLOB", 0, TK_GLOB, 0 },
{ "INDEX", 0, TK_INDEX, 0 },
{ "INSERT", 0, TK_INSERT, 0 },
{ "INTO", 0, TK_INTO, 0 },
{ "IS", 0, TK_IS, 0 },
{ "ISNULL", 0, TK_ISNULL, 0 },
{ "KEY", 0, TK_KEY, 0 },
+ { "LIKE", 0, TK_LIKE, 0 },
{ "NOT", 0, TK_NOT, 0 },
{ "NOTNULL", 0, TK_NOTNULL, 0 },
{ "NULL", 0, TK_NULL, 0 },
@@ -83,6 +85,7 @@ static Keyword aKeywordTable[] = {
{ "UNIQUE", 0, TK_UNIQUE, 0 },
{ "UPDATE", 0, TK_UPDATE, 0 },
{ "USING", 0, TK_USING, 0 },
+ { "VACUUM", 0, TK_VACUUM, 0 },
{ "VALUES", 0, TK_VALUES, 0 },
{ "WHERE", 0, TK_WHERE, 0 },
};
diff --git a/src/util.c b/src/util.c
index 1c59ad7d57..b5bf19ca65 100644
--- a/src/util.c
+++ b/src/util.c
@@ -26,7 +26,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.6 2000/05/30 16:27:04 drh Exp $
+** $Id: util.c,v 1.7 2000/05/31 02:27:49 drh Exp $
*/
#include "sqliteInt.h"
#include
@@ -563,3 +563,138 @@ int sqliteSortCompare(const char *a, const char *b){
if( *a=='-' ) res = -res;
return res;
}
+
+/*
+** Compare two strings for equality where the first string can
+** potentially be a "glob" expression. Return true (1) if they
+** are the same and false (0) if they are different.
+**
+** Globbing rules:
+**
+** '*' Matches any sequence of zero or more characters.
+**
+** '?' Matches exactly one character.
+**
+** [...] Matches one character from the enclosed list of
+** characters.
+**
+** [^...] Matches one character not in the enclosed list.
+**
+** With the [...] and [^...] matching, a ']' character can be included
+** in the list by making it the first character after '[' or '^'. A
+** range of characters can be specified using '-'. Example:
+** "[a-z]" matches any single lower-case letter. To match a '-', make
+** it the last character in the list.
+**
+** This routine is usually quick, but can be N**2 in the worst case.
+**
+** Hints: to match '*' or '?', put them in "[]". Like this:
+**
+** abc[*]xyz Matches "abc*xyz" only
+*/
+int sqliteGlobCompare(const char *zPattern, const char *zString){
+ register char c;
+ int invert;
+ int seen;
+ char c2;
+
+ while( (c = *zPattern)!=0 ){
+ switch( c ){
+ case '*':
+ while( zPattern[1]=='*' ) zPattern++;
+ if( zPattern[1]==0 ) return 1;
+ c = zPattern[1];
+ if( c=='[' || c=='?' ){
+ while( *zString && sqliteGlobCompare(&zPattern[1],zString)==0 ){
+ zString++;
+ }
+ return *zString!=0;
+ }else{
+ while( (c2 = *zString)!=0 ){
+ while( c2 != 0 && c2 != c ){ c2 = *++zString; }
+ if( sqliteGlobCompare(&zPattern[1],zString) ) return 1;
+ zString++;
+ }
+ return 0;
+ }
+ case '?':
+ if( *zString==0 ) return 0;
+ break;
+ case '[':
+ seen = 0;
+ invert = 0;
+ c = *zString;
+ if( c==0 ) return 0;
+ c2 = *++zPattern;
+ if( c2=='^' ){ invert = 1; c2 = *++zPattern; }
+ if( c2==']' ){
+ if( c==']' ) seen = 1;
+ c2 = *++zPattern;
+ }
+ while( (c2 = *zPattern)!=0 && c2!=']' ){
+ if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 ){
+ if( c>zPattern[-1] && ctos;
+ int nos = tos - 1;
+ int c;
+ if( nos<0 ) goto not_enough_stack;
+ Stringify(p, tos);
+ Stringify(p, nos);
+ c = sqliteLikeCompare(p->zStack[tos], p->zStack[nos]);
+ PopStack(p, 2);
+ if( pOp->p1 ) c = !c;
+ if( c ) pc = pOp->p2-1;
+ break;
+ }
+
+ /* Opcode: Glob P1 P2 *
+ **
+ ** Pop the top two elements from the stack. The top-most is a
+ ** "glob" pattern. The lower element is the string to compare
+ ** against the glob pattern.
+ **
+ ** Jump to P2 if the two compare, and fall through without
+ ** jumping if they do not. The '*' in the top-most element matches
+ ** any sequence of zero or more characters in the lower element. The
+ ** '?' character in the topmost matches any single character of the
+ ** lower element. [...] matches a range of characters. [^...]
+ ** matches any character not in the range. Case is significant
+ ** for globs.
+ **
+ ** If P1 is not zero, the sense of the test is inverted and we
+ ** have a "NOT GLOB" operator. The jump is made if the two values
+ ** are different.
+ */
+ case OP_Glob: {
+ int tos = p->tos;
+ int nos = tos - 1;
+ int c;
+ if( nos<0 ) goto not_enough_stack;
+ Stringify(p, tos);
+ Stringify(p, nos);
+ c = sqliteGlobCompare(p->zStack[tos], p->zStack[nos]);
+ PopStack(p, 2);
+ if( pOp->p1 ) c = !c;
+ if( c ) pc = pOp->p2-1;
+ break;
+ }
+
/* Opcode: And * * *
**
** Pop two values off the stack. Take the logical AND of the
@@ -1581,6 +1643,15 @@ int sqliteVdbeExec(
break;
}
+ /* Opcode: Reorganize * * P3
+ **
+ ** Compress, optimize, and tidy up the GDBM file named by P3.
+ */
+ case OP_Reorganize: {
+ sqliteDbbeReorganizeTable(p->pBe, pOp->p3);
+ break;
+ }
+
/* Opcode: ListOpen P1 * *
**
** Open a file used for temporary storage of index numbers. P1
diff --git a/src/vdbe.h b/src/vdbe.h
index d5dca045ec..3672cfee35 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -27,7 +27,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.2 2000/05/30 16:27:05 drh Exp $
+** $Id: vdbe.h,v 1.3 2000/05/31 02:27:50 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@@ -73,81 +73,86 @@ typedef struct VdbeOp VdbeOp;
*/
#define OP_Open 1
#define OP_Close 2
-#define OP_Destroy 3
-#define OP_Fetch 4
-#define OP_New 5
-#define OP_Put 6
-#define OP_Delete 7
-#define OP_Field 8
-#define OP_Key 9
-#define OP_Rewind 10
-#define OP_Next 11
-#define OP_ResetIdx 12
-#define OP_NextIdx 13
-#define OP_PutIdx 14
-#define OP_DeleteIdx 15
+#define OP_Fetch 3
+#define OP_New 4
+#define OP_Put 5
+#define OP_Delete 6
+#define OP_Field 7
+#define OP_Key 8
+#define OP_Rewind 9
+#define OP_Next 10
-#define OP_ListOpen 16
-#define OP_ListWrite 17
-#define OP_ListRewind 18
-#define OP_ListRead 19
-#define OP_ListClose 20
+#define OP_Destroy 11
+#define OP_Reorganize 12
-#define OP_SortOpen 21
-#define OP_SortPut 22
-#define OP_SortMakeRec 23
-#define OP_SortMakeKey 24
-#define OP_Sort 25
-#define OP_SortNext 26
-#define OP_SortKey 27
-#define OP_SortCallback 28
-#define OP_SortClose 29
+#define OP_ResetIdx 13
+#define OP_NextIdx 14
+#define OP_PutIdx 15
+#define OP_DeleteIdx 16
-#define OP_FileOpen 30
-#define OP_FileRead 31
-#define OP_FileField 32
-#define OP_FileClose 33
+#define OP_ListOpen 17
+#define OP_ListWrite 18
+#define OP_ListRewind 19
+#define OP_ListRead 20
+#define OP_ListClose 21
-#define OP_MakeRecord 34
-#define OP_MakeKey 35
+#define OP_SortOpen 22
+#define OP_SortPut 23
+#define OP_SortMakeRec 24
+#define OP_SortMakeKey 25
+#define OP_Sort 26
+#define OP_SortNext 27
+#define OP_SortKey 28
+#define OP_SortCallback 29
+#define OP_SortClose 30
-#define OP_Goto 36
-#define OP_If 37
-#define OP_Halt 38
+#define OP_FileOpen 31
+#define OP_FileRead 32
+#define OP_FileField 33
+#define OP_FileClose 34
-#define OP_ColumnCount 39
-#define OP_ColumnName 40
-#define OP_Callback 41
+#define OP_MakeRecord 35
+#define OP_MakeKey 36
-#define OP_Integer 42
-#define OP_String 43
-#define OP_Pop 44
-#define OP_Dup 45
-#define OP_Pull 46
+#define OP_Goto 37
+#define OP_If 38
+#define OP_Halt 39
-#define OP_Add 47
-#define OP_AddImm 48
-#define OP_Subtract 49
-#define OP_Multiply 50
-#define OP_Divide 51
-#define OP_Min 52
-#define OP_Max 53
-#define OP_Eq 54
-#define OP_Ne 55
-#define OP_Lt 56
-#define OP_Le 57
-#define OP_Gt 58
-#define OP_Ge 59
-#define OP_IsNull 60
-#define OP_NotNull 61
-#define OP_Negative 62
-#define OP_And 63
-#define OP_Or 64
-#define OP_Not 65
-#define OP_Concat 66
-#define OP_Noop 67
+#define OP_ColumnCount 40
+#define OP_ColumnName 41
+#define OP_Callback 42
-#define OP_MAX 67
+#define OP_Integer 43
+#define OP_String 44
+#define OP_Pop 45
+#define OP_Dup 46
+#define OP_Pull 47
+
+#define OP_Add 48
+#define OP_AddImm 49
+#define OP_Subtract 50
+#define OP_Multiply 51
+#define OP_Divide 52
+#define OP_Min 53
+#define OP_Max 54
+#define OP_Like 55
+#define OP_Glob 56
+#define OP_Eq 57
+#define OP_Ne 58
+#define OP_Lt 59
+#define OP_Le 60
+#define OP_Gt 61
+#define OP_Ge 62
+#define OP_IsNull 63
+#define OP_NotNull 64
+#define OP_Negative 65
+#define OP_And 66
+#define OP_Or 67
+#define OP_Not 68
+#define OP_Concat 69
+#define OP_Noop 70
+
+#define OP_MAX 70
/*
** Prototypes for the VDBE interface. See comments on the implementation
diff --git a/src/where.c b/src/where.c
index 4efabff20a..217bfd342b 100644
--- a/src/where.c
+++ b/src/where.c
@@ -25,7 +25,7 @@
** the WHERE clause of SQL statements. Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
-** $Id: where.c,v 1.3 2000/05/30 20:17:49 drh Exp $
+** $Id: where.c,v 1.4 2000/05/31 02:27:50 drh Exp $
*/
#include "sqliteInt.h"
@@ -368,12 +368,14 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
case TK_SLASH: op = OP_Divide; break;
case TK_AND: op = OP_And; break;
case TK_OR: op = OP_Or; break;
- case TK_LT: op = OP_Ge; break;
- case TK_LE: op = OP_Gt; break;
- case TK_GT: op = OP_Le; break;
- case TK_GE: op = OP_Lt; break;
- case TK_NE: op = OP_Eq; break;
- case TK_EQ: op = OP_Ne; break;
+ case TK_LT: op = OP_Lt; break;
+ case TK_LE: op = OP_Le; break;
+ case TK_GT: op = OP_Gt; break;
+ case TK_GE: op = OP_Ge; break;
+ case TK_NE: op = OP_Ne; break;
+ case TK_EQ: op = OP_Eq; break;
+ case TK_LIKE: op = OP_Like; break;
+ case TK_GLOB: op = OP_Glob; break;
case TK_ISNULL: op = OP_IsNull; break;
case TK_NOTNULL: op = OP_NotNull; break;
case TK_NOT: op = OP_Not; break;
@@ -421,14 +423,16 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
case TK_GT:
case TK_GE:
case TK_NE:
- case TK_EQ: {
+ case TK_EQ:
+ case TK_LIKE:
+ case TK_GLOB: {
int dest;
- sqliteVdbeAddOp(v, OP_Integer, 0, 0, 0, 0);
+ sqliteVdbeAddOp(v, OP_Integer, 1, 0, 0, 0);
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
dest = sqliteVdbeCurrentAddr(v) + 2;
sqliteVdbeAddOp(v, op, 0, dest, 0, 0);
- sqliteVdbeAddOp(v, OP_AddImm, 1, 0, 0, 0);
+ sqliteVdbeAddOp(v, OP_AddImm, -1, 0, 0, 0);
break;
}
case TK_NOT:
@@ -466,6 +470,8 @@ void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest){
case TK_GE: op = OP_Ge; break;
case TK_NE: op = OP_Ne; break;
case TK_EQ: op = OP_Eq; break;
+ case TK_LIKE: op = OP_Like; break;
+ case TK_GLOB: op = OP_Glob; break;
case TK_ISNULL: op = OP_IsNull; break;
case TK_NOTNULL: op = OP_NotNull; break;
default: break;
@@ -483,12 +489,18 @@ void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest){
sqliteExprIfTrue(pParse, pExpr->pRight, dest);
break;
}
+ case TK_NOT: {
+ sqliteExprIfFalse(pParse, pExpr->pLeft, dest);
+ break;
+ }
case TK_LT:
case TK_LE:
case TK_GT:
case TK_GE:
case TK_NE:
- case TK_EQ: {
+ case TK_EQ:
+ case TK_LIKE:
+ case TK_GLOB: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
sqliteVdbeAddOp(v, op, 0, dest, 0, 0);
@@ -523,6 +535,8 @@ void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest){
case TK_GE: op = OP_Lt; break;
case TK_NE: op = OP_Eq; break;
case TK_EQ: op = OP_Ne; break;
+ case TK_LIKE: op = OP_Like; break;
+ case TK_GLOB: op = OP_Glob; break;
case TK_ISNULL: op = OP_NotNull; break;
case TK_NOTNULL: op = OP_IsNull; break;
default: break;
@@ -540,6 +554,10 @@ void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest){
sqliteVdbeResolveLabel(v, d2);
break;
}
+ case TK_NOT: {
+ sqliteExprIfTrue(pParse, pExpr->pLeft, dest);
+ break;
+ }
case TK_LT:
case TK_LE:
case TK_GT:
@@ -551,6 +569,13 @@ void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest){
sqliteVdbeAddOp(v, op, 0, dest, 0, 0);
break;
}
+ case TK_LIKE:
+ case TK_GLOB: {
+ sqliteExprCode(pParse, pExpr->pLeft);
+ sqliteExprCode(pParse, pExpr->pRight);
+ sqliteVdbeAddOp(v, op, 1, dest, 0, 0);
+ break;
+ }
case TK_ISNULL:
case TK_NOTNULL: {
sqliteExprCode(pParse, pExpr->pLeft);
diff --git a/www/changes.tcl b/www/changes.tcl
new file mode 100644
index 0000000000..fa52187e88
--- /dev/null
+++ b/www/changes.tcl
@@ -0,0 +1,46 @@
+#
+# Run this script to generated a changes.html output file
+#
+puts {
+
+ SQLite Change Log
+
+
+Recent Changes To SQLite
+
+
+}
+
+
+proc chng {date desc} {
+ puts "- $date
"
+ puts "
"
+}
+
+chng {2000 May 30} {
+Added the LIKE operator.
+Added a GLOB operator: similar to LIKE
+but it uses Unix shell globbing wildcards instead of the '%'
+and '_' wildcards of SQL.
+Added the COPY command patterned after
+PostgreSQL so that SQLite
+can now read the output of the pg_dump database dump utility
+of PostgreSQL.
+Added a VACUUM command that that calls the
+gdbm_reorganize() function on the underlying database
+files.
+And many, many bug fixes...
+}
+
+chng {2000 May 29} {
+Initial Public Release of Alpha code
+}
+
+puts {
+
+
+
+Back to the SQLite Home Page
+
+
+}
diff --git a/www/index.tcl b/www/index.tcl
index badc1da977..24a87a44c8 100644
--- a/www/index.tcl
+++ b/www/index.tcl
@@ -1,7 +1,7 @@
#
# Run this TCL script to generate HTML for the index.html file.
#
-set rcsid {$Id: index.tcl,v 1.4 2000/05/30 00:05:13 drh Exp $}
+set rcsid {$Id: index.tcl,v 1.5 2000/05/31 02:27:50 drh Exp $}
puts {
SQLite: An SQL Frontend For GDBM
@@ -47,6 +47,9 @@ can be used as an example of how to interact with the SQLite C
library. For more information on the sqlite program,
see sqlite.html.
+A history of changes to SQLite is found
+here.
+
SQLite does not try to implement every feature of SQL. But it
does strive to implement to most commonly used features. SQLite
currently understands the following SQL commands:
@@ -71,7 +74,6 @@ implement are as follows:
- ALTER TABLE
- The GROUP BY or HAVING clauses of a SELECT
-- The LIKE or IN operators
- The COUNT(), MAX(), MIN(), and AVG() functions
- Constraints
- Nested queries
diff --git a/www/sqlite.tcl b/www/sqlite.tcl
index a69b3763e9..873d3e28f0 100644
--- a/www/sqlite.tcl
+++ b/www/sqlite.tcl
@@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the sqlite.html file.
#
-set rcsid {$Id: sqlite.tcl,v 1.3 2000/05/29 18:50:16 drh Exp $}
+set rcsid {$Id: sqlite.tcl,v 1.4 2000/05/31 02:27:50 drh Exp $}
puts {
@@ -354,6 +354,18 @@ SELECT sql FROM sqlite_master
ORDER BY tbl_name, type DESC, name
+Of, if you give an argument to ".schema" because you only
+one the schema for a single table, the query looks like this:
+
+
+SELECT sql FROM sqlite_master
+WHERE tbl_name LIKE '%s'
+ORDER BY type DESC, name
+
+
+The %s in the query above is replaced by the argument
+to ".schema", of course.
+
Other Dot Commands
The ".explain" dot command can be used to set the output mode