1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

:-) (CVS 20)

FossilOrigin-Name: 01d85b35e9c4ca5619ad21a4232a8f8bf9ec3538
This commit is contained in:
drh
2000-05-31 02:27:49 +00:00
parent 7e391e1728
commit dce2cbe65f
17 changed files with 505 additions and 131 deletions

View File

@ -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;
}

View File

@ -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>
@ -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().
*/

View File

@ -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*);

View File

@ -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);}

View File

@ -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 "

View File

@ -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*);

View File

@ -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 },
};

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);