Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix for ticket #1: Implement the GLOB and LIKE operators as functions that can be overridden. This way, a developer can change the LIKE operator to be case sensitive, for example. (CVS 537) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
51572bf71774d7631c7083be90b806e6 |
User & Date: | drh 2002-04-20 14:24:42.000 |
Context
2002-04-20
| ||
14:44 | Update the change log for the 2.4.8 release. (CVS 539) (check-in: c01bc2d19e user: drh tags: trunk) | |
14:24 | Fix for ticket #1: Implement the GLOB and LIKE operators as functions that can be overridden. This way, a developer can change the LIKE operator to be case sensitive, for example. (CVS 537) (check-in: 51572bf717 user: drh tags: trunk) | |
2002-04-19
| ||
12:34 | Add support for saving the sqlite shell command-line history across sessions. (CVS 536) (check-in: ca4abf3fe1 user: drh tags: trunk) | |
Changes
Changes to VERSION.
|
| | | 1 | 2.4.8 |
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.58 2002/04/20 14:24:42 drh Exp $ */ #include "sqliteInt.h" /* ** Construct a new expression node and return a pointer to it. Memory ** for this node is obtained from sqliteMalloc(). The calling function |
︙ | ︙ | |||
701 702 703 704 705 706 707 | case TK_OR: op = OP_Or; 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; | < < | 701 702 703 704 705 706 707 708 709 710 711 712 713 714 | case TK_OR: op = OP_Or; 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_ISNULL: op = OP_IsNull; break; case TK_NOTNULL: op = OP_NotNull; break; case TK_NOT: op = OP_Not; break; case TK_UMINUS: op = OP_Negative; break; case TK_BITAND: op = OP_BitAnd; break; case TK_BITOR: op = OP_BitOr; break; case TK_BITNOT: op = OP_BitNot; break; |
︙ | ︙ | |||
780 781 782 783 784 785 786 | break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: | | < < | 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 | break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { int dest; sqliteVdbeAddOp(v, OP_Integer, 1, 0); sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); dest = sqliteVdbeCurrentAddr(v) + 2; sqliteVdbeAddOp(v, op, 0, dest); sqliteVdbeAddOp(v, OP_AddImm, -1, 0); |
︙ | ︙ | |||
934 935 936 937 938 939 940 | switch( pExpr->op ){ 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; | < < | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 | switch( pExpr->op ){ 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_ISNULL: op = OP_IsNull; break; case TK_NOTNULL: op = OP_NotNull; break; default: break; } switch( pExpr->op ){ case TK_AND: { int d2 = sqliteVdbeMakeLabel(v); |
︙ | ︙ | |||
962 963 964 965 966 967 968 | break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: | | < < | 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 | break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, 0, dest); break; } case TK_ISNULL: case TK_NOTNULL: { |
︙ | ︙ | |||
1022 1023 1024 1025 1026 1027 1028 | switch( pExpr->op ){ 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; | < < | 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 | switch( pExpr->op ){ 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_ISNULL: op = OP_NotNull; break; case TK_NOTNULL: op = OP_IsNull; break; default: break; } switch( pExpr->op ){ case TK_AND: { sqliteExprIfFalse(pParse, pExpr->pLeft, dest); |
︙ | ︙ | |||
1056 1057 1058 1059 1060 1061 1062 | case TK_NE: case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, 0, dest); break; } | < < < < < < < | 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 | case TK_NE: case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, 0, dest); break; } case TK_ISNULL: case TK_NOTNULL: { sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, op, 0, dest); break; } case TK_IN: { |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.16 2002/04/20 14:24:42 drh Exp $ */ #include <ctype.h> #include <math.h> #include <stdlib.h> #include <assert.h> #include "sqliteInt.h" |
︙ | ︙ | |||
196 197 198 199 200 201 202 | sqlite_set_result_int(context, sqliteRandomInteger()); } /* ** Implementation of the last_insert_rowid() SQL function. The return ** value is the same as the sqlite_last_insert_rowid() API function. */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | sqlite_set_result_int(context, sqliteRandomInteger()); } /* ** Implementation of the last_insert_rowid() SQL function. The return ** value is the same as the sqlite_last_insert_rowid() API function. */ static void last_insert_rowid(sqlite_func *context, int arg, const char **argv){ sqlite *db = sqlite_user_data(context); sqlite_set_result_int(context, sqlite_last_insert_rowid(db)); } /* ** Implementation of the like() SQL function. This function implements ** the build-in LIKE operator. The first argument to the function is the ** string and the second argument is the pattern. So, the SQL statements: ** ** A LIKE B ** ** is implemented as like(A,B). */ static void likeFunc(sqlite_func *context, int arg, const char **argv){ sqlite_set_result_int(context, sqliteLikeCompare(argv[0] ? argv[0] : "",argv[1] ? argv[1] : "")); } /* ** Implementation of the glob() SQL function. This function implements ** the build-in GLOB operator. The first argument to the function is the ** string and the second argument is the pattern. So, the SQL statements: ** ** A GLOB B ** ** is implemented as glob(A,B). */ static void globFunc(sqlite_func *context, int arg, const char **argv){ sqlite_set_result_int(context, sqliteGlobCompare(argv[0] ? argv[0] : "",argv[1] ? argv[1] : "")); } /* ** An instance of the following structure holds the context of a ** sum() or avg() aggregate computation. */ typedef struct SumCtx SumCtx; struct SumCtx { |
︙ | ︙ | |||
390 391 392 393 394 395 396 397 398 399 400 401 402 403 | { "round", 2, roundFunc }, { "upper", 1, upperFunc }, { "lower", 1, lowerFunc }, { "coalesce", -1, ifnullFunc }, { "coalesce", 0, 0 }, { "coalesce", 1, 0 }, { "random", -1, randomFunc }, }; static struct { char *zName; int nArg; void (*xStep)(sqlite_func*,int,const char**); void (*xFinalize)(sqlite_func*); } aAggs[] = { | > > | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | { "round", 2, roundFunc }, { "upper", 1, upperFunc }, { "lower", 1, lowerFunc }, { "coalesce", -1, ifnullFunc }, { "coalesce", 0, 0 }, { "coalesce", 1, 0 }, { "random", -1, randomFunc }, { "like", 2, likeFunc }, { "glob", 2, globFunc }, }; static struct { char *zName; int nArg; void (*xStep)(sqlite_func*,int,const char**); void (*xFinalize)(sqlite_func*); } aAggs[] = { |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.62 2002/04/20 14:24:42 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { sqliteSetString(&pParse->zErrMsg,"syntax error",0); |
︙ | ︙ | |||
427 428 429 430 431 432 433 | 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) BITAND expr(Y). {A = sqliteExpr(TK_BITAND, X, Y, 0);} expr(A) ::= expr(X) BITOR expr(Y). {A = sqliteExpr(TK_BITOR, X, Y, 0);} expr(A) ::= expr(X) LSHIFT expr(Y). {A = sqliteExpr(TK_LSHIFT, X, Y, 0);} expr(A) ::= expr(X) RSHIFT expr(Y). {A = sqliteExpr(TK_RSHIFT, X, Y, 0);} | < | > | | | < | > > | > > | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 | 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) BITAND expr(Y). {A = sqliteExpr(TK_BITAND, X, Y, 0);} expr(A) ::= expr(X) BITOR expr(Y). {A = sqliteExpr(TK_BITOR, X, Y, 0);} expr(A) ::= expr(X) LSHIFT expr(Y). {A = sqliteExpr(TK_LSHIFT, X, Y, 0);} expr(A) ::= expr(X) RSHIFT expr(Y). {A = sqliteExpr(TK_RSHIFT, X, Y, 0);} expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE] { ExprList *pList = sqliteExprListAppend(0, Y, 0); pList = sqliteExprListAppend(pList, X, 0); A = sqliteExprFunction(pList, &OP); sqliteExprSpan(A, &X->span, &Y->span); } expr(A) ::= expr(X) NOT likeop(OP) expr(Y). [LIKE] { ExprList *pList = sqliteExprListAppend(0, Y, 0); pList = sqliteExprListAppend(pList, X, 0); A = sqliteExprFunction(pList, &OP); A = sqliteExpr(TK_NOT, A, 0, 0); sqliteExprSpan(A,&X->span,&Y->span); } likeop(A) ::= LIKE(X). {A = X;} likeop(A) ::= GLOB(X). {A = X;} 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);} expr(A) ::= expr(X) SLASH expr(Y). {A = sqliteExpr(TK_SLASH, X, Y, 0);} expr(A) ::= expr(X) REM expr(Y). {A = sqliteExpr(TK_REM, X, Y, 0);} expr(A) ::= expr(X) CONCAT expr(Y). {A = sqliteExpr(TK_CONCAT, X, Y, 0);} expr(A) ::= expr(X) ISNULL(E). { |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.139 2002/04/20 14:24:42 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
1054 1055 1056 1057 1058 1059 1060 | "MakeKey", "MakeIdxKey", "IncrKey", "Goto", "If", "Halt", "ColumnCount", "ColumnName", "Callback", "NullCallback", "Integer", "String", "Pop", "Dup", "Pull", "Push", "MustBeInt", "Add", "AddImm", "Subtract", "Multiply", "Divide", "Remainder", "BitAnd", "BitOr", "BitNot", "ShiftLeft", "ShiftRight", | | | | | | | 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | "MakeKey", "MakeIdxKey", "IncrKey", "Goto", "If", "Halt", "ColumnCount", "ColumnName", "Callback", "NullCallback", "Integer", "String", "Pop", "Dup", "Pull", "Push", "MustBeInt", "Add", "AddImm", "Subtract", "Multiply", "Divide", "Remainder", "BitAnd", "BitOr", "BitNot", "ShiftLeft", "ShiftRight", "AbsValue", "Eq", "Ne", "Lt", "Le", "Gt", "Ge", "IsNull", "NotNull", "Negative", "And", "Or", "Not", "Concat", "Noop", "Function", "Limit", }; /* ** Given the name of an opcode, return its number. Return 0 if ** there is no match. ** ** This routine is used for testing and debugging. |
︙ | ︙ | |||
2003 2004 2005 2006 2007 2008 2009 | case OP_Lt: c = c<0; break; case OP_Le: c = c<=0; break; case OP_Gt: c = c>0; break; default: c = c>=0; break; } POPSTACK; POPSTACK; | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 | case OP_Lt: c = c<0; break; case OP_Le: c = c<=0; break; case OP_Gt: c = c>0; break; default: c = c>=0; break; } POPSTACK; POPSTACK; if( c ) pc = pOp->p2-1; break; } /* Opcode: And * * * ** ** Pop two values off the stack. Take the logical AND of the |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** 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.50 2002/04/20 14:24:43 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
176 177 178 179 180 181 182 | #define OP_Remainder 91 #define OP_BitAnd 92 #define OP_BitOr 93 #define OP_BitNot 94 #define OP_ShiftLeft 95 #define OP_ShiftRight 96 #define OP_AbsValue 97 | < < | | | | | | | | | | | | | | | | | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | #define OP_Remainder 91 #define OP_BitAnd 92 #define OP_BitOr 93 #define OP_BitNot 94 #define OP_ShiftLeft 95 #define OP_ShiftRight 96 #define OP_AbsValue 97 #define OP_Eq 98 #define OP_Ne 99 #define OP_Lt 100 #define OP_Le 101 #define OP_Gt 102 #define OP_Ge 103 #define OP_IsNull 104 #define OP_NotNull 105 #define OP_Negative 106 #define OP_And 107 #define OP_Or 108 #define OP_Not 109 #define OP_Concat 110 #define OP_Noop 111 #define OP_Function 112 #define OP_Limit 113 #define OP_MAX 113 /* ** Prototypes for the VDBE interface. See comments on the implementation ** for a description of what each of these routines does. */ Vdbe *sqliteVdbeCreate(sqlite*); void sqliteVdbeCreateCallback(Vdbe*, int*); |
︙ | ︙ |
Changes to tool/speedtest.tcl.
︙ | ︙ | |||
28 29 30 31 32 33 34 | regsub -all \n [string trim $sql] <br> sql } puts "<blockquote>" puts "$sql" puts "</blockquote><table border=0 cellpadding=0 cellspacing=0>" set format {<tr><td>%s</td><td align="right"> %.3f</td></tr>} set delay 1000 | | | | | | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | regsub -all \n [string trim $sql] <br> sql } puts "<blockquote>" puts "$sql" puts "</blockquote><table border=0 cellpadding=0 cellspacing=0>" set format {<tr><td>%s</td><td align="right"> %.3f</td></tr>} set delay 1000 # exec sync; after $delay; # set t [time "exec psql drh <$sqlfile" 1] # set t [expr {[lindex $t 0]/1000000.0}] # puts [format $format PostgreSQL: $t] exec sync; after $delay; set t [time "exec mysql -f drh <$sqlfile" 1] set t [expr {[lindex $t 0]/1000000.0}] puts [format $format MySQL: $t] # set t [time "exec ./sqlite232 s232.db <$sqlfile" 1] # set t [expr {[lindex $t 0]/1000000.0}] # puts [format $format {SQLite 2.3.2:} $t] # set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1] # set t [expr {[lindex $t 0]/1000000.0}] # puts [format $format {SQLite 2.4 (cache=100):} $t] exec sync; after $delay; set t [time "exec ./sqlite248 s2k.db <$sqlfile" 1] set t [expr {[lindex $t 0]/1000000.0}] puts [format $format {SQLite 2.4:} $t] exec sync; after $delay; set t [time "exec ./sqlite248 sns.db <$sqlfile" 1] set t [expr {[lindex $t 0]/1000000.0}] puts [format $format {SQLite 2.4 (nosync):} $t] # set t [time "exec ./sqlite-t1 st1.db <$sqlfile" 1] # set t [expr {[lindex $t 0]/1000000.0}] # puts [format $format {SQLite 2.4 (test):} $t] puts "</table>" } |
︙ | ︙ | |||
74 75 76 77 78 79 80 | catch {exec mysql drh <clear.sql} set fd [open 2kinit.sql w] puts $fd { PRAGMA default_cache_size=2000; PRAGMA default_synchronous=on; } close $fd | | | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | catch {exec mysql drh <clear.sql} set fd [open 2kinit.sql w] puts $fd { PRAGMA default_cache_size=2000; PRAGMA default_synchronous=on; } close $fd exec ./sqlite248 s2k.db <2kinit.sql set fd [open nosync-init.sql w] puts $fd { PRAGMA default_cache_size=2000; PRAGMA default_synchronous=off; } close $fd exec ./sqlite248 sns.db <nosync-init.sql set ones {zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen} set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety} proc number_name {n} { if {$n>=1000} { set txt "[number_name [expr {$n/1000}]] thousand" |
︙ | ︙ |