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 "

    $desc

" +} + +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