/ Check-in [0eef538f]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added length() and substr() functions (CVS 143)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0eef538f3de66fede7c88f8be8c3458d84107c3f
User & Date: drh 2000-08-28 15:51:44
Context
2000-08-28
16:21
adding length() and substr() tests. fix shell.c bug (CVS 144) check-in: b8cec9b9 user: drh tags: trunk
15:51
Added length() and substr() functions (CVS 143) check-in: 0eef538f user: drh tags: trunk
2000-08-22
18:30
Version 1.0.3 (CVS 497) check-in: d35a1f8b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
319
320
321
322
323
324
325


326
327
328
329
330
331
332
...
376
377
378
379
380
381
382










383
384
385
386
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
...
570
571
572
573
574
575
576

577
578
579
580


581
582
583
584
585



















586
587
588
589
590
591
592
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** 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 $
*/
#include "sqliteInt.h"

/*
** Walk an expression tree.  Return 1 if the expression is constant
** and 0 if it involves variables.
*/
................................................................................
  } aFunc[] = {
     { "count",  5, FN_Count },
     { "min",    3, FN_Min   },
     { "max",    3, FN_Max   },
     { "sum",    3, FN_Sum   },
     { "avg",    3, FN_Avg   },
     { "fcnt",   4, FN_Fcnt  },  /* Used for testing only */


  };
  int i;
  for(i=0; i<ArraySize(aFunc); i++){
    if( aFunc[i].len==pToken->n 
     && sqliteStrNICmp(pToken->z, aFunc[i].zName, aFunc[i].len)==0 ){
       return aFunc[i].id;
    }
................................................................................
        case FN_Avg:
        case FN_Sum: {
          no_such_func = !allowAgg;
          too_many_args = n>1;
          too_few_args = n<1;
          is_agg = 1;
          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
        ** to verify that indices are being used properly to minimize
        ** searching.  All arguments to fcnt() are ignored.  fcnt() has
        ** no use (other than testing) that we are aware of.
        */
        case FN_Fcnt: {
          n = 0;
          break;
        }

        default: break;
      }
      if( no_such_func ){
        sqliteSetNString(&pParse->zErrMsg, "no such function: ", -1,
           pExpr->token.z, pExpr->token.n, 0);
        pParse->nErr++;
        nErr++;
................................................................................
      break;
    }
    case TK_FUNCTION: {
      int id = pExpr->iColumn;
      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);



















        }
      }
      break;
    }
    case TK_SELECT: {
      sqliteVdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0, 0, 0);
      break;







|







 







>
>







 







>
>
>
>
>
>
>
>
>
>












>







 







>
|
|
|
|
>
>
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
...
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions.
**
** $Id: expr.c,v 1.19 2000/08/28 15:51:44 drh Exp $
*/
#include "sqliteInt.h"

/*
** Walk an expression tree.  Return 1 if the expression is constant
** and 0 if it involves variables.
*/
................................................................................
  } aFunc[] = {
     { "count",  5, FN_Count },
     { "min",    3, FN_Min   },
     { "max",    3, FN_Max   },
     { "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++){
    if( aFunc[i].len==pToken->n 
     && sqliteStrNICmp(pToken->z, aFunc[i].zName, aFunc[i].len)==0 ){
       return aFunc[i].id;
    }
................................................................................
        case FN_Avg:
        case FN_Sum: {
          no_such_func = !allowAgg;
          too_many_args = n>1;
          too_few_args = n<1;
          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
        ** to verify that indices are being used properly to minimize
        ** searching.  All arguments to fcnt() are ignored.  fcnt() has
        ** no use (other than testing) that we are aware of.
        */
        case FN_Fcnt: {
          n = 0;
          break;
        }
      
        default: break;
      }
      if( no_such_func ){
        sqliteSetNString(&pParse->zErrMsg, "no such function: ", -1,
           pExpr->token.z, pExpr->token.n, 0);
        pParse->nErr++;
        nErr++;
................................................................................
      break;
    }
    case TK_FUNCTION: {
      int id = pExpr->iColumn;
      int op;
      int i;
      ExprList *pList = pExpr->pList;
      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;
    }
    case TK_SELECT: {
      sqliteVdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0, 0, 0);
      break;

Changes to src/sqliteInt.h.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
95
96
97
98
99
100
101


102
103
104
105
106
107
108
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.29 2000/08/02 13:47:42 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
#define FN_Unknown    0
#define FN_Count      1
#define FN_Min        2
#define FN_Max        3
#define FN_Sum        4
#define FN_Avg        5
#define FN_Fcnt       6



/*
** Forward references to structures
*/
typedef struct Column Column;
typedef struct Table Table;
typedef struct Index Index;







|







 







>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.30 2000/08/28 15:51:44 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
#define FN_Unknown    0
#define FN_Count      1
#define FN_Min        2
#define FN_Max        3
#define FN_Sum        4
#define FN_Avg        5
#define FN_Fcnt       6
#define FN_Length     7
#define FN_Substr     8

/*
** Forward references to structures
*/
typedef struct Column Column;
typedef struct Table Table;
typedef struct Index Index;

Changes to src/vdbe.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
784
785
786
787
788
789
790

791
792
793
794
795
796
797
....
3125
3126
3127
3128
3129
3130
3131





















































































3132
3133
3134
3135
3136
3137
3138
** inplicit conversion from one 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.38 2000/08/02 12:26:29 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
................................................................................
  "String",         "Null",           "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",

};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.
................................................................................
        Stringify(p, tos);
        if( i>=0 && i<p->nSet && !SetTest(&p->aSet[i], p->zStack[tos]) ){
          pc = pOp->p2 - 1;
        }
        PopStack(p, 1);
        break;
      }






















































































      /* An other opcode is illegal...
      */
      default: {
        sprintf(zBuf,"%d",pOp->opcode);
        sqliteSetString(pzErrMsg, "unknown opcode ", zBuf, 0);
        rc = SQLITE_INTERNAL;







|







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
....
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
** inplicit conversion from one 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.39 2000/08/28 15:51:44 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
................................................................................
  "String",         "Null",           "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",
  "Strlen",         "Substr",       
};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.
................................................................................
        Stringify(p, tos);
        if( i>=0 && i<p->nSet && !SetTest(&p->aSet[i], p->zStack[tos]) ){
          pc = pOp->p2 - 1;
        }
        PopStack(p, 1);
        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: {
        sprintf(zBuf,"%d",pOp->opcode);
        sqliteSetString(pzErrMsg, "unknown opcode ", zBuf, 0);
        rc = SQLITE_INTERNAL;

Changes to src/vdbe.h.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
169
170
171
172
173
174
175



176
177
178
179
180
181
182
183
*************************************************************************
** 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.11 2000/07/28 14:32:50 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
#define OP_Negative           83
#define OP_And                84
#define OP_Or                 85
#define OP_Not                86
#define OP_Concat             87
#define OP_Noop               88




#define OP_MAX                88

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(Dbbe*);
int sqliteVdbeAddOp(Vdbe*,int,int,int,const char*,int);







|







 







>
>
>
|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
*************************************************************************
** 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.12 2000/08/28 15:51:45 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
#define OP_Negative           83
#define OP_And                84
#define OP_Or                 85
#define OP_Not                86
#define OP_Concat             87
#define OP_Noop               88

#define OP_Strlen             89
#define OP_Substr             90

#define OP_MAX                90

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(Dbbe*);
int sqliteVdbeAddOp(Vdbe*,int,int,int,const char*,int);