]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Added length() and substr() functions (CVS 143)
authordrh <drh@noemail.net>
Mon, 28 Aug 2000 15:51:43 +0000 (15:51 +0000)
committerdrh <drh@noemail.net>
Mon, 28 Aug 2000 15:51:43 +0000 (15:51 +0000)
FossilOrigin-Name: 0eef538f3de66fede7c88f8be8c3458d84107c3f

manifest
manifest.uuid
src/expr.c
src/sqliteInt.h
src/vdbe.c
src/vdbe.h

index fcc64deb1a9c9a8b50252f81d533d0c8bb16b11c..daa7d4f11d6e0a043ee110f49071530fefcb89ac 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Version\s1.0.3\s(CVS\s497)
-D 2000-08-22T18:30:00
+C Added\slength()\sand\ssubstr()\sfunctions\s(CVS\s143)
+D 2000-08-28T15:51:44
 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
 F Makefile.in 036bce328b963f48dbaadbec8cc4144a1fd9e50a
 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
@@ -11,7 +11,7 @@ F src/build.c 4d90e9e94750ca80249fc7958c617021d8bb7a50
 F src/dbbe.c 226daaf8c095ceb4aff48cad188dad90643f9867
 F src/dbbe.h 6337132f904e72ecb28b07390021c241397e4cbf
 F src/delete.c 4d491eaf61b515516749c7ed68fa3b2ee8a09065
-F src/expr.c 2fa63f086707176d09092e71832f9bbdc6a8ac85
+F src/expr.c e8e350d7baa33bd9ed8701c159eaba5e912e0adb
 F src/insert.c f146f149ad2422a1dc3bfa7a1651a25940f98958
 F src/main.c 9a89579b40e498920f86e89878f52185457b9c2c
 F src/parse.y 5d199034de5d29ebedb42c1c51f34db4df40cbe5
@@ -19,13 +19,13 @@ F src/select.c d382e96c2221d08367cc87976f2b574537c9de97
 F src/shell.c 061186b1a4f0884037d067f0f102ec5d382119b5
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
 F src/sqlite.h.in d341439fc1432c7d7014bcff5f7b6e914571232c
-F src/sqliteInt.h f6d1e139b3bfa4ceff2136684e19d76b53178ec0
+F src/sqliteInt.h b65fdecac7281aafb4c9ff3e79ea1b5546478385
 F src/tclsqlite.c 89dc4ba2b521f3e919d6d7aaa4cc1c2aba8e16f3
 F src/tokenize.c 097bec5843d4a0fb4509e036fee93bac080c5e73
 F src/update.c 51b9ef7434b15e31096155da920302e9db0d27fc
 F src/util.c b75b33e6bd5d47898bb7ed9fdd0dea4fe7c19b00
-F src/vdbe.c bdedf21230581f0cf73a2dcd8fe23f30cf30ebe6
-F src/vdbe.h 6c5653241633c583549c2d8097394ab52550eb63
+F src/vdbe.c a2372aebfcf2a5ed4530cd956a8cdbb595c67991
+F src/vdbe.h 6413cd0165ac62b0839fe3e077cb7c9f0b736295
 F src/where.c 3dfad2ffd0aa994d5eceac88852f7189c8d1d3c8
 F test/all.test 0950c135cab7e60c07bd745ccfad1476211e5bd7
 F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
@@ -70,7 +70,7 @@ F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60
 F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
 F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
 F www/vdbe.tcl bcbfc33bcdd0ebad95eab31286adb9e1bc289520
-P f255ea6d4bb085a869485c14b4c96af13ca826fa
-R d941b15d38d95642a66b6ff4bba2c454
+P d35a1f8b37333e2df86c22c2dbd766132b4931b2
+R 33478b7323acb1d67e1ce4b66b8bba30
 U drh
-Z cbdf4324aa4508ca2f8e72c3acf62235
+Z a1f7d622d82864a914f4580098647f78
index 75314479acfe789fe787fd9987f829e9d228cf5e..8b147137cd9d1c57f779b688a7ad9b85fb94403d 100644 (file)
@@ -1 +1 @@
-d35a1f8b37333e2df86c22c2dbd766132b4931b2
\ No newline at end of file
+0eef538f3de66fede7c88f8be8c3458d84107c3f
\ No newline at end of file
index c94fd247a4666b4fc6203e7e6207ae1c3924738e..55774f24b4d0702f5b08534ad5f5bcc2d41c0e7b 100644 (file)
@@ -24,7 +24,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions.
 **
-** $Id: expr.c,v 1.18 2000/06/21 13:59:11 drh Exp $
+** $Id: expr.c,v 1.19 2000/08/28 15:51:44 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -323,6 +323,8 @@ int sqliteFuncId(Token *pToken){
      { "sum",    3, FN_Sum   },
      { "avg",    3, FN_Avg   },
      { "fcnt",   4, FN_Fcnt  },  /* Used for testing only */
+     { "length", 6, FN_Length},
+     { "substr", 6, FN_Substr},
   };
   int i;
   for(i=0; i<ArraySize(aFunc); i++){
@@ -381,6 +383,16 @@ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
           is_agg = 1;
           break;
         }
+        case FN_Length: {
+          too_few_args = n<1;
+          too_many_args = n>1;
+          break;
+        }
+        case FN_Substr: {
+          too_few_args = n<3;
+          too_many_args = n>3;
+          break;
+        }
         /* The "fcnt(*)" function always returns the number of fetch
         ** operations that have occurred so far while processing the
         ** SQL statement.  This information can be used by test procedures
@@ -392,6 +404,7 @@ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
           n = 0;
           break;
         }
+      
         default: break;
       }
       if( no_such_func ){
@@ -574,15 +587,37 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
       int op;
       int i;
       ExprList *pList = pExpr->pList;
-      if( id==FN_Fcnt ){
-        sqliteVdbeAddOp(v, OP_Fcnt, 0, 0, 0, 0);
-        break;
-      }
-      op = id==FN_Min ? OP_Min : OP_Max;
-      for(i=0; i<pList->nExpr; i++){
-        sqliteExprCode(pParse, pList->a[i].pExpr);
-        if( i>0 ){
-          sqliteVdbeAddOp(v, op, 0, 0, 0, 0);
+      switch( id ){
+        case FN_Fcnt: {
+          sqliteVdbeAddOp(v, OP_Fcnt, 0, 0, 0, 0);
+          break;
+        }
+        case FN_Min: 
+        case FN_Max: {
+          op = id==FN_Min ? OP_Min : OP_Max;
+          for(i=0; i<pList->nExpr; i++){
+            sqliteExprCode(pParse, pList->a[i].pExpr);
+            if( i>0 ){
+              sqliteVdbeAddOp(v, op, 0, 0, 0, 0);
+            }
+          }
+          break;
+        }
+        case FN_Length: {
+          sqliteExprCode(pParse, pList->a[0].pExpr);
+          sqliteVdbeAddOp(v, OP_Strlen, 0, 0, 0, 0);
+          break;
+        }
+        case FN_Substr: {
+          for(i=0; i<pList->nExpr; i++){
+            sqliteExprCode(pParse, pList->a[i].pExpr);
+          }
+          sqliteVdbeAddOp(v, OP_Substr, 0, 0, 0, 0);
+          break;
+        }
+        default: {
+          /* Can't happen! */
+          break;
         }
       }
       break;
index 3e497f3b4fdc5457c30c4e02eeaf11ce52955635..092feb5b674eaeb037b8b794da01e8eac3a79ec5 100644 (file)
@@ -23,7 +23,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.29 2000/08/02 13:47:42 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.30 2000/08/28 15:51:44 drh Exp $
 */
 #include "sqlite.h"
 #include "dbbe.h"
@@ -99,6 +99,8 @@ int sqlite_iMallocFail;     /* Fail sqliteMalloc() after this many calls */
 #define FN_Sum        4
 #define FN_Avg        5
 #define FN_Fcnt       6
+#define FN_Length     7
+#define FN_Substr     8
 
 /*
 ** Forward references to structures
index 48505068556ff4523e3bb0df2868530f9aa94604..d258beaa5ee21bda438a842f1ccf0e972694b5d5 100644 (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.38 2000/08/02 12:26:29 drh Exp $
+** $Id: vdbe.c,v 1.39 2000/08/28 15:51:44 drh Exp $
 */
 #include "sqliteInt.h"
 #include <unistd.h>
@@ -788,6 +788,7 @@ static char *zOpName[] = { 0,
   "Lt",             "Le",             "Gt",             "Ge",
   "IsNull",         "NotNull",        "Negative",       "And",
   "Or",             "Not",            "Concat",         "Noop",
+  "Strlen",         "Substr",       
 };
 
 /*
@@ -3130,6 +3131,91 @@ int sqliteVdbeExec(
         break;
       }
 
+      /* Opcode: Length * * *
+      **
+      ** Interpret the top of the stack as a string.  Replace the top of
+      ** stack with an integer which is the length of the string.
+      */
+      case OP_Strlen: {
+        int tos = p->tos;
+        int len;
+        if( tos<0 ) goto not_enough_stack;
+        Stringify(p, tos);
+        len = p->aStack[tos].n-1;
+        PopStack(p, 1);
+        p->tos++;
+        p->aStack[tos].i = len;
+        p->aStack[tos].flags = STK_Int;
+        break;
+      }
+
+      /* Opcode: Substr P1 P2 *
+      **
+      ** This operation pops between 1 and 3 elements from the stack and
+      ** pushes back a single element.  The bottom-most element popped from
+      ** the stack is a string and the element pushed back is also a string.
+      ** The other two elements popped are integers.  The integers are taken
+      ** from the stack only if P1 and/or P2 are 0.  When P1 or P2 are
+      ** not zero, the value of the operand is used rather than the integer
+      ** from the stack.  In the sequel, we will use P1 and P2 to describe
+      ** the two integers, even if those integers are really taken from the
+      ** stack.
+      **
+      ** The string pushed back onto the stack is a substring of the string
+      ** that was popped.  There are P2 characters in the substring.  The
+      ** first character of the substring is the P1-th character of the
+      ** original string where the left-most character is 1 (not 0).  If P1
+      ** is negative, then counting begins at the right instead of at the
+      ** left.
+      */
+      case OP_Substr: {
+        int cnt;
+        int start;
+        int n;
+        char *z;
+
+        if( pOp->p2==0 ){
+          if( p->tos<0 ) goto not_enough_stack;
+          Integerify(p, p->tos);
+          cnt = p->aStack[p->tos].i;
+          PopStack(p, 1);
+        }else{
+          cnt = pOp->p2;
+        }
+        if( pOp->p1==0 ){
+          if( p->tos<0 ) goto not_enough_stack;
+          Integerify(p, p->tos);
+          start = p->aStack[p->tos].i;
+          PopStack(p, 1);
+        }else{
+          start = pOp->p1;
+        }
+        if( p->tos<0 ) goto not_enough_stack;
+        Stringify(p, p->tos);
+        n = p->aStack[p->tos].n - 1;
+        if( start<0 ){
+          start += n;
+          if( start<0 ){
+            cnt += start;
+            start = 0;
+          }
+        }
+        if( cnt<0 ) cnt = 0;
+        if( cnt > n ){
+          cnt = n;
+        }
+        z = sqliteMalloc( cnt+1 );
+        if( z==0 ) goto no_mem;
+        strncpy(z, p->zStack[p->tos], cnt);
+        z[cnt] = 0;
+        PopStack(p, 1);
+        p->tos++;
+        p->zStack[p->tos] = z;
+        p->aStack[p->tos].n = cnt + 1;
+        p->aStack[p->tos].flags = STK_Str|STK_Dyn;
+        break;
+      }
+
       /* An other opcode is illegal...
       */
       default: {
index bf80b1849b434738daa0b9cc8612eed58b033f40..d349b5dc85958edde5adea1a4cfc0c80c8c3cd0a 100644 (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.11 2000/07/28 14:32:50 drh Exp $
+** $Id: vdbe.h,v 1.12 2000/08/28 15:51:45 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -173,7 +173,10 @@ typedef struct VdbeOp VdbeOp;
 #define OP_Concat             87
 #define OP_Noop               88
 
-#define OP_MAX                88
+#define OP_Strlen             89
+#define OP_Substr             90
+
+#define OP_MAX                90
 
 /*
 ** Prototypes for the VDBE interface.  See comments on the implementation