diff options
author | drh <drh@noemail.net> | 2000-05-31 02:27:49 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2000-05-31 02:27:49 +0000 |
commit | dce2cbe65f9bedf260d320c775d59727a6ddb9bb (patch) | |
tree | f8a0b3281313cedf3734d4284fd1204548bcb2fb /src | |
parent | 7e391e1728770cf09f0b544e9a417990292235cd (diff) | |
download | sqlite-dce2cbe65f9bedf260d320c775d59727a6ddb9bb.tar.gz sqlite-dce2cbe65f9bedf260d320c775d59727a6ddb9bb.zip |
:-) (CVS 20)
FossilOrigin-Name: 01d85b35e9c4ca5619ad21a4232a8f8bf9ec3538
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 45 | ||||
-rw-r--r-- | src/dbbe.c | 18 | ||||
-rw-r--r-- | src/dbbe.h | 5 | ||||
-rw-r--r-- | src/parse.y | 11 | ||||
-rw-r--r-- | src/shell.c | 6 | ||||
-rw-r--r-- | src/sqliteInt.h | 5 | ||||
-rw-r--r-- | src/tokenize.c | 5 | ||||
-rw-r--r-- | src/util.c | 137 | ||||
-rw-r--r-- | src/vdbe.c | 107 | ||||
-rw-r--r-- | src/vdbe.h | 157 | ||||
-rw-r--r-- | src/where.c | 47 |
11 files changed, 426 insertions, 117 deletions
diff --git a/src/build.c b/src/build.c index 4b29cc187..fd0aaeef3 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; h<N_HASH; h++){ + for(pTab=pParse->db->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 51cf86b0b..0e96bf85e 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 <gdbm.h> @@ -200,6 +200,22 @@ void sqliteDbbeDropTable(Dbbe *pBe, const char *zTable){ } /* +** 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(). */ void sqliteDbbeCloseTable(DbbeTable *pTable){ diff --git a/src/dbbe.h b/src/dbbe.h index 26e83a648..c9f424d49 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 7b58846e6..89d003575 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 b044ad46e..4cc8a3032 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 <stdlib.h> #include <string.h> @@ -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 7bbabff15..c64a14737 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 ac062d0b5..d47476ff7 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 <ctype.h> @@ -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 1c59ad7d5..b5bf19ca6 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 <stdarg.h> @@ -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] && c<zPattern[1] ) seen = 1; + }else if( c==c2 ){ + seen = 1; + } + zPattern++; + } + if( c2==0 || (seen ^ invert)==0 ) return 0; + break; + default: + if( c != *zString ) return 0; + break; + } + zPattern++; + zString++; + } + return *zString==0; +} + +/* +** Compare two strings for equality using the "LIKE" operator of +** SQL. The '%' character matches any sequence of 0 or more +** characters and '_' matches any single character. Case is +** not significant. +** +** This routine is just an adaptation of the sqliteGlobCompare() +** routine above. +*/ +int +sqliteLikeCompare(const unsigned char *zPattern, const unsigned char *zString){ + register char c; + int invert; + int seen; + char c2; + + while( (c = UpperToLower[*zPattern])!=0 ){ + switch( c ){ + case '%': + while( zPattern[1]=='%' ) zPattern++; + if( zPattern[1]==0 ) return 1; + c = UpperToLower[0xff & zPattern[1]]; + if( c=='_' ){ + while( *zString && sqliteLikeCompare(&zPattern[1],zString)==0 ){ + zString++; + } + return *zString!=0; + }else{ + while( (c2 = UpperToLower[*zString])!=0 ){ + while( c2 != 0 && c2 != c ){ c2 = UpperToLower[*++zString]; } + if( sqliteLikeCompare(&zPattern[1],zString) ) return 1; + zString++; + } + return 0; + } + case '_': + if( *zString==0 ) return 0; + break; + default: + if( c != UpperToLower[*zString] ) return 0; + break; + } + zPattern++; + zString++; + } + return *zString==0; +} diff --git a/src/vdbe.c b/src/vdbe.c index de87f9646..62ed2e956 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -41,7 +41,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.2 2000/05/30 16:27:04 drh Exp $ +** $Id: vdbe.c,v 1.3 2000/05/31 02:27:50 drh Exp $ */ #include "sqliteInt.h" @@ -391,23 +391,24 @@ void sqliteVdbeDelete(Vdbe *p){ ** this array, then copy and paste it into this file, if you want. */ static char *zOpName[] = { 0, - "Open", "Close", "Destroy", "Fetch", - "New", "Put", "Delete", "Field", - "Key", "Rewind", "Next", "ResetIdx", - "NextIdx", "PutIdx", "DeleteIdx", "ListOpen", - "ListWrite", "ListRewind", "ListRead", "ListClose", - "SortOpen", "SortPut", "SortMakeRec", "SortMakeKey", - "Sort", "SortNext", "SortKey", "SortCallback", - "SortClose", "FileOpen", "FileRead", "FileField", - "FileClose", "MakeRecord", "MakeKey", "Goto", - "If", "Halt", "ColumnCount", "ColumnName", - "Callback", "Integer", "String", "Pop", - "Dup", "Pull", "Add", "AddImm", - "Subtract", "Multiply", "Divide", "Min", - "Max", "Eq", "Ne", "Lt", - "Le", "Gt", "Ge", "IsNull", - "NotNull", "Negative", "And", "Or", - "Not", "Concat", "Noop", + "Open", "Close", "Fetch", "New", + "Put", "Delete", "Field", "Key", + "Rewind", "Next", "Destroy", "Reorganize", + "ResetIdx", "NextIdx", "PutIdx", "DeleteIdx", + "ListOpen", "ListWrite", "ListRewind", "ListRead", + "ListClose", "SortOpen", "SortPut", "SortMakeRec", + "SortMakeKey", "Sort", "SortNext", "SortKey", + "SortCallback", "SortClose", "FileOpen", "FileRead", + "FileField", "FileClose", "MakeRecord", "MakeKey", + "Goto", "If", "Halt", "ColumnCount", + "ColumnName", "Callback", "Integer", "String", + "Pop", "Dup", "Pull", "Add", + "AddImm", "Subtract", "Multiply", "Divide", + "Min", "Max", "Like", "Glob", + "Eq", "Ne", "Lt", "Le", + "Gt", "Ge", "IsNull", "NotNull", + "Negative", "And", "Or", "Not", + "Concat", "Noop", }; /* @@ -997,6 +998,67 @@ int sqliteVdbeExec( break; } + /* Opcode: Like P1 P2 * + ** + ** Pop the top two elements from the stack. The top-most is a + ** "like" pattern -- the right operand of the SQL "LIKE" operator. + ** The lower element is the string to compare against the like + ** 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. Case is ignored for this comparison. + ** + ** If P1 is not zero, the sense of the test is inverted and we + ** have a "NOT LIKE" operator. The jump is made if the two values + ** are different. + */ + case OP_Like: { + int tos = p->tos; + 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 d5dca045e..3672cfee3 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_ListOpen 16 -#define OP_ListWrite 17 -#define OP_ListRewind 18 -#define OP_ListRead 19 -#define OP_ListClose 20 - -#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_FileOpen 30 -#define OP_FileRead 31 -#define OP_FileField 32 -#define OP_FileClose 33 - -#define OP_MakeRecord 34 -#define OP_MakeKey 35 - -#define OP_Goto 36 -#define OP_If 37 -#define OP_Halt 38 - -#define OP_ColumnCount 39 -#define OP_ColumnName 40 -#define OP_Callback 41 - -#define OP_Integer 42 -#define OP_String 43 -#define OP_Pop 44 -#define OP_Dup 45 -#define OP_Pull 46 - -#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_MAX 67 +#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_Destroy 11 +#define OP_Reorganize 12 + +#define OP_ResetIdx 13 +#define OP_NextIdx 14 +#define OP_PutIdx 15 +#define OP_DeleteIdx 16 + +#define OP_ListOpen 17 +#define OP_ListWrite 18 +#define OP_ListRewind 19 +#define OP_ListRead 20 +#define OP_ListClose 21 + +#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_FileOpen 31 +#define OP_FileRead 32 +#define OP_FileField 33 +#define OP_FileClose 34 + +#define OP_MakeRecord 35 +#define OP_MakeKey 36 + +#define OP_Goto 37 +#define OP_If 38 +#define OP_Halt 39 + +#define OP_ColumnCount 40 +#define OP_ColumnName 41 +#define OP_Callback 42 + +#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 4efabff20..217bfd342 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); |