]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
The REGEXP operator is recognized. It tries to invoke a function named
authordrh <drh@noemail.net>
Mon, 23 May 2005 17:26:51 +0000 (17:26 +0000)
committerdrh <drh@noemail.net>
Mon, 23 May 2005 17:26:51 +0000 (17:26 +0000)
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

manifest
manifest.uuid
src/expr.c
src/parse.y
tool/mkkeywordhash.c

index b3cc33eed5cbc2fef778a6ed495ade323dce25ee..8e0afa62e84793802c7ff957267f54fc59a49cb9 100644 (file)
--- a/manifest
+++ b/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
index f9adbff574b7aeb1f9fb05161054939255855a27..107d1b8a2ffc51b5355a47ecdb9829320aa96c96 100644 (file)
@@ -1 +1 @@
-ef4059e3afa1a61a9e59df00cdfedc57d8df9fec
\ No newline at end of file
+42a626ace126f730f33ecb6c41ac5679d6766a31
\ No newline at end of file
index 6237e75d21698ee0f10c87893b29f75d4e7289bd..7373fdc5744f08ed611b309790709f2afe445628 100644 (file)
@@ -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);
index 2b8d052d1004e13e0bb2c9d354c965028bdc63e1..1f7c8af33381588e5480514c9fe09ff2a2be4771 100644 (file)
@@ -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);
 }
index 582412452e1948c84e6f33ed33d1355500051c09..5d3425709155d622bcfcb267fc8b09455057fee0 100644 (file)
@@ -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               },