mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Added length() and substr() functions (CVS 143)
FossilOrigin-Name: 0eef538f3de66fede7c88f8be8c3458d84107c3f
This commit is contained in:
18
manifest
18
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
|
||||
|
@@ -1 +1 @@
|
||||
d35a1f8b37333e2df86c22c2dbd766132b4931b2
|
||||
0eef538f3de66fede7c88f8be8c3458d84107c3f
|
39
src/expr.c
39
src/expr.c
@@ -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,10 +587,13 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
|
||||
int op;
|
||||
int i;
|
||||
ExprList *pList = pExpr->pList;
|
||||
if( id==FN_Fcnt ){
|
||||
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);
|
||||
@@ -587,6 +603,25 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
|
||||
}
|
||||
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;
|
||||
|
@@ -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
|
||||
|
88
src/vdbe.c
88
src/vdbe.c
@@ -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: {
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user