The REGEXP operator is recognized. It tries to invoke a function named
regexp() which does not exist in the native build. But users who want to can add an appropriate regexp() function using sqlite3_create_function(). (CVS 2478) FossilOrigin-Name: 42a626ace126f730f33ecb6c41ac5679d6766a31
This commit is contained in:
parent
15ccce1c0d
commit
b71090fdfb
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
||||
C Make\ssure\sthat\sthe\suse\sof\sa\sdouble-quoted\sstring\sliteral\sdoes\snot\strick\nthe\soptimizer\sinto\susing\sa\scorrelated\ssubquery\swhen\sa\sstatic\nsubquery\swould\ssuffice.\s(CVS\s2477)
|
||||
D 2005-05-23T15:06:39
|
||||
C The\sREGEXP\soperator\sis\srecognized.\s\sIt\stries\sto\sinvoke\sa\sfunction\snamed\r\nregexp()\swhich\sdoes\snot\sexist\sin\sthe\snative\sbuild.\s\sBut\susers\swho\swant\sto\r\ncan\sadd\san\sappropriate\sregexp()\sfunction\susing\ssqlite3_create_function().\s(CVS\s2478)
|
||||
D 2005-05-23T17:26:51
|
||||
F Makefile.in 5c00d0037104de2a50ac7647a5f12769795957a3
|
||||
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -36,7 +36,7 @@ F src/build.c 6770abc63df9f3ed9f44c50411bb63692cb4589f
|
||||
F src/date.c 2134ef4388256e8247405178df8a61bd60dc180a
|
||||
F src/delete.c 75b53db21aa1879d3655bbbc208007db31d58a63
|
||||
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
|
||||
F src/expr.c f2ff12d9970d844564ec8b3ce4ea702bf6730b6a
|
||||
F src/expr.c d0fbb951fd260feb2e2028c5ec078e98daca5bb6
|
||||
F src/func.c d09df82e35ef988cd28a3ffd63cd772271b7def9
|
||||
F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
|
||||
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
||||
@ -54,7 +54,7 @@ F src/os_win.c 2bbbe6fbb010763c3fa79d5e951afca9b138c6b5
|
||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c f86d79d37eb4e30d8e2201dbe12497370719320c
|
||||
F src/pager.h 0d9153d6269d60d04af3dd84a0cc0a96253cf4a4
|
||||
F src/parse.y 3e314b3a96b199b0501ed426f2cee3392ffce806
|
||||
F src/parse.y 72cd7553f05fbc7b63ea9476108d0da6237f2818
|
||||
F src/pragma.c 0ed94a1aa982802a9cf2a932c48d99b60683fa53
|
||||
F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
|
||||
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||
@ -223,7 +223,7 @@ F tool/lempar.c f0c30abcae762a7d1eb37cd88b2232ab8dd625fb
|
||||
F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133
|
||||
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
|
||||
F tool/memleak3.tcl 009da0ea82dc5893edca76cf1a21fb7260e9412e
|
||||
F tool/mkkeywordhash.c 02ac5c523fd6d55364cd70aded5c36ba6651a6bf
|
||||
F tool/mkkeywordhash.c 596389943f516bf6eaddd46659e7b87b16ea7c33
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
|
||||
@ -279,7 +279,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
||||
F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
|
||||
P f7b76d02e003faf0310b87949d3cb0f38062853f
|
||||
R 7f9d3157fe368f24bc8a9f1b20f7fe23
|
||||
P ef4059e3afa1a61a9e59df00cdfedc57d8df9fec
|
||||
R 8996a199d8872550587b98a7437c931f
|
||||
U drh
|
||||
Z b4157a0f7dc132bb0373ae1877998e51
|
||||
Z 797c50f3e25833784eb0ca0d6800d861
|
||||
|
@ -1 +1 @@
|
||||
ef4059e3afa1a61a9e59df00cdfedc57d8df9fec
|
||||
42a626ace126f730f33ecb6c41ac5679d6766a31
|
63
src/expr.c
63
src/expr.c
@ -12,7 +12,7 @@
|
||||
** This file contains routines used for analyzing expressions and
|
||||
** for generating VDBE code that evaluates expressions in SQLite.
|
||||
**
|
||||
** $Id: expr.c,v 1.199 2005/05/23 15:06:39 drh Exp $
|
||||
** $Id: expr.c,v 1.200 2005/05/23 17:26:51 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -994,49 +994,6 @@ lookupname_end_2:
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** pExpr is a node that defines a function of some kind. It might
|
||||
** be a syntactic function like "count(x)" or it might be a function
|
||||
** that implements an operator, like "a LIKE b".
|
||||
**
|
||||
** This routine makes *pzName point to the name of the function and
|
||||
** *pnName hold the number of characters in the function name.
|
||||
*/
|
||||
static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
|
||||
switch( pExpr->op ){
|
||||
case TK_FUNCTION: {
|
||||
*pzName = pExpr->token.z;
|
||||
*pnName = pExpr->token.n;
|
||||
break;
|
||||
}
|
||||
case TK_LIKE: {
|
||||
*pzName = "like";
|
||||
*pnName = 4;
|
||||
break;
|
||||
}
|
||||
case TK_GLOB: {
|
||||
*pzName = "glob";
|
||||
*pnName = 4;
|
||||
break;
|
||||
}
|
||||
case TK_CTIME: {
|
||||
*pzName = "current_time";
|
||||
*pnName = 12;
|
||||
break;
|
||||
}
|
||||
case TK_CDATE: {
|
||||
*pzName = "current_date";
|
||||
*pnName = 12;
|
||||
break;
|
||||
}
|
||||
case TK_CTIMESTAMP: {
|
||||
*pzName = "current_timestamp";
|
||||
*pnName = 17;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is designed as an xFunc for walkExprTree().
|
||||
**
|
||||
@ -1111,11 +1068,7 @@ static int nameResolverStep(void *pArg, Expr *pExpr){
|
||||
|
||||
/* Resolve function names
|
||||
*/
|
||||
case TK_CTIME:
|
||||
case TK_CTIMESTAMP:
|
||||
case TK_CDATE:
|
||||
case TK_GLOB:
|
||||
case TK_LIKE:
|
||||
case TK_CONST_FUNC:
|
||||
case TK_FUNCTION: {
|
||||
ExprList *pList = pExpr->pList; /* The argument list */
|
||||
int n = pList ? pList->nExpr : 0; /* Number of arguments */
|
||||
@ -1128,7 +1081,8 @@ static int nameResolverStep(void *pArg, Expr *pExpr){
|
||||
FuncDef *pDef; /* Information about the function */
|
||||
int enc = pParse->db->enc; /* The database encoding */
|
||||
|
||||
getFunctionName(pExpr, &zId, &nId);
|
||||
zId = pExpr->token.z;
|
||||
nId = pExpr->token.n;
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
|
||||
if( pDef==0 ){
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
|
||||
@ -1544,11 +1498,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
|
||||
break;
|
||||
}
|
||||
case TK_CDATE:
|
||||
case TK_CTIME:
|
||||
case TK_CTIMESTAMP:
|
||||
case TK_GLOB:
|
||||
case TK_LIKE:
|
||||
case TK_CONST_FUNC:
|
||||
case TK_FUNCTION: {
|
||||
ExprList *pList = pExpr->pList;
|
||||
int nExpr = pList ? pList->nExpr : 0;
|
||||
@ -1559,7 +1509,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
int i;
|
||||
u8 enc = pParse->db->enc;
|
||||
CollSeq *pColl = 0;
|
||||
getFunctionName(pExpr, &zId, &nId);
|
||||
zId = pExpr->token.z;
|
||||
nId = pExpr->token.n;
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
|
||||
assert( pDef!=0 );
|
||||
nExpr = sqlite3ExprCodeExprList(pParse, pList);
|
||||
|
34
src/parse.y
34
src/parse.y
@ -14,7 +14,7 @@
|
||||
** the parser. Lemon will also generate a header file containing
|
||||
** numeric codes for all of the tokens.
|
||||
**
|
||||
** @(#) $Id: parse.y,v 1.171 2005/04/22 02:38:38 drh Exp $
|
||||
** @(#) $Id: parse.y,v 1.172 2005/05/23 17:26:51 drh Exp $
|
||||
*/
|
||||
%token_prefix TK_
|
||||
%token_type {Token}
|
||||
@ -48,8 +48,8 @@ struct LimitVal {
|
||||
** GLOB, NOT LIKE, and NOT GLOB operators.
|
||||
*/
|
||||
struct LikeOp {
|
||||
int opcode; /* Either TK_GLOB or TK_LIKE */
|
||||
int not; /* True if the NOT keyword is present */
|
||||
Token operator; /* "like" or "glob" or "regexp" */
|
||||
int not; /* True if the NOT keyword is present */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -75,7 +75,7 @@ struct AttachKey { int type; Token key; };
|
||||
// add them to the parse.h output file.
|
||||
//
|
||||
%nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
|
||||
COLUMN AGG_FUNCTION.
|
||||
COLUMN AGG_FUNCTION CONST_FUNC.
|
||||
|
||||
// Input is a single SQL command
|
||||
input ::= cmdlist.
|
||||
@ -153,13 +153,13 @@ id(A) ::= ID(X). {A = X;}
|
||||
%fallback ID
|
||||
ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CONFLICT
|
||||
DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
|
||||
GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY
|
||||
IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH KEY
|
||||
OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
|
||||
TEMP TRIGGER VACUUM VIEW
|
||||
%ifdef SQLITE_OMIT_COMPOUND_SELECT
|
||||
EXCEPT INTERSECT UNION
|
||||
%endif
|
||||
REINDEX RENAME CDATE CTIME CTIMESTAMP ALTER
|
||||
REINDEX RENAME CTIME_KW ALTER
|
||||
.
|
||||
|
||||
// Define operator precedence early so that this is the first occurance
|
||||
@ -176,7 +176,7 @@ id(A) ::= ID(X). {A = X;}
|
||||
%left OR.
|
||||
%left AND.
|
||||
%right NOT.
|
||||
%left IS LIKE GLOB BETWEEN IN ISNULL NOTNULL NE EQ.
|
||||
%left IS LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
|
||||
%left GT LE LT GE.
|
||||
%right ESCAPE.
|
||||
%left BITAND BITOR LSHIFT RSHIFT.
|
||||
@ -627,9 +627,12 @@ expr(A) ::= ID(X) LP STAR RP(E). {
|
||||
A = sqlite3ExprFunction(0, &X);
|
||||
sqlite3ExprSpan(A,&X,&E);
|
||||
}
|
||||
term(A) ::= CTIME(OP). {A = sqlite3Expr(@OP,0,0,0);}
|
||||
term(A) ::= CDATE(OP). {A = sqlite3Expr(@OP,0,0,0);}
|
||||
term(A) ::= CTIMESTAMP(OP). {A = sqlite3Expr(@OP,0,0,0);}
|
||||
term(A) ::= CTIME_KW(OP). {
|
||||
/* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
|
||||
** treated as functions that return constants */
|
||||
A = sqlite3ExprFunction(0,&OP);
|
||||
if( A ) A->op = TK_CONST_FUNC;
|
||||
}
|
||||
expr(A) ::= expr(X) AND(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
|
||||
expr(A) ::= expr(X) OR(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
|
||||
expr(A) ::= expr(X) LT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
|
||||
@ -649,21 +652,18 @@ expr(A) ::= expr(X) SLASH(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
|
||||
expr(A) ::= expr(X) REM(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
|
||||
expr(A) ::= expr(X) CONCAT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
|
||||
%type likeop {struct LikeOp}
|
||||
likeop(A) ::= LIKE. {A.opcode = TK_LIKE; A.not = 0;}
|
||||
likeop(A) ::= GLOB. {A.opcode = TK_GLOB; A.not = 0;}
|
||||
likeop(A) ::= NOT LIKE. {A.opcode = TK_LIKE; A.not = 1;}
|
||||
likeop(A) ::= NOT GLOB. {A.opcode = TK_GLOB; A.not = 1;}
|
||||
likeop(A) ::= LIKE_KW(X). {A.operator = X; A.not = 0;}
|
||||
likeop(A) ::= NOT LIKE_KW(X). {A.operator = X; A.not = 1;}
|
||||
%type escape {Expr*}
|
||||
escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;}
|
||||
escape(X) ::= . [ESCAPE] {X = 0;}
|
||||
expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE] {
|
||||
expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] {
|
||||
ExprList *pList = sqlite3ExprListAppend(0, Y, 0);
|
||||
pList = sqlite3ExprListAppend(pList, X, 0);
|
||||
if( E ){
|
||||
pList = sqlite3ExprListAppend(pList, E, 0);
|
||||
}
|
||||
A = sqlite3ExprFunction(pList, 0);
|
||||
if( A ) A->op = OP.opcode;
|
||||
A = sqlite3ExprFunction(pList, &OP.operator);
|
||||
if( OP.not ) A = sqlite3Expr(TK_NOT, A, 0, 0);
|
||||
sqlite3ExprSpan(A, &X->span, &Y->span);
|
||||
}
|
||||
|
@ -125,9 +125,9 @@ static Keyword aKeywordTable[] = {
|
||||
{ "CONSTRAINT", "TK_CONSTRAINT", ALWAYS },
|
||||
{ "CREATE", "TK_CREATE", ALWAYS },
|
||||
{ "CROSS", "TK_JOIN_KW", ALWAYS },
|
||||
{ "CURRENT_DATE", "TK_CDATE", ALWAYS },
|
||||
{ "CURRENT_TIME", "TK_CTIME", ALWAYS },
|
||||
{ "CURRENT_TIMESTAMP","TK_CTIMESTAMP", ALWAYS },
|
||||
{ "CURRENT_DATE", "TK_CTIME_KW", ALWAYS },
|
||||
{ "CURRENT_TIME", "TK_CTIME_KW", ALWAYS },
|
||||
{ "CURRENT_TIMESTAMP","TK_CTIME_KW", ALWAYS },
|
||||
{ "DATABASE", "TK_DATABASE", ATTACH },
|
||||
{ "DEFAULT", "TK_DEFAULT", ALWAYS },
|
||||
{ "DEFERRED", "TK_DEFERRED", ALWAYS },
|
||||
@ -150,7 +150,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "FOREIGN", "TK_FOREIGN", FKEY },
|
||||
{ "FROM", "TK_FROM", ALWAYS },
|
||||
{ "FULL", "TK_JOIN_KW", ALWAYS },
|
||||
{ "GLOB", "TK_GLOB", ALWAYS },
|
||||
{ "GLOB", "TK_LIKE_KW", ALWAYS },
|
||||
{ "GROUP", "TK_GROUP", ALWAYS },
|
||||
{ "HAVING", "TK_HAVING", ALWAYS },
|
||||
{ "IGNORE", "TK_IGNORE", CONFLICT|TRIGGER },
|
||||
@ -168,7 +168,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "JOIN", "TK_JOIN", ALWAYS },
|
||||
{ "KEY", "TK_KEY", ALWAYS },
|
||||
{ "LEFT", "TK_JOIN_KW", ALWAYS },
|
||||
{ "LIKE", "TK_LIKE", ALWAYS },
|
||||
{ "LIKE", "TK_LIKE_KW", ALWAYS },
|
||||
{ "LIMIT", "TK_LIMIT", ALWAYS },
|
||||
{ "MATCH", "TK_MATCH", ALWAYS },
|
||||
{ "NATURAL", "TK_JOIN_KW", ALWAYS },
|
||||
@ -185,6 +185,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "PRIMARY", "TK_PRIMARY", ALWAYS },
|
||||
{ "RAISE", "TK_RAISE", TRIGGER },
|
||||
{ "REFERENCES", "TK_REFERENCES", FKEY },
|
||||
{ "REGEXP", "TK_LIKE_KW", ALWAYS },
|
||||
{ "REINDEX", "TK_REINDEX", REINDEX },
|
||||
{ "RENAME", "TK_RENAME", ALTER },
|
||||
{ "REPLACE", "TK_REPLACE", CONFLICT },
|
||||
|
Loading…
x
Reference in New Issue
Block a user