1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

2.0.3 (CVS 287)

FossilOrigin-Name: 75e90cf09b64ee1fcb39a711fc9ac6d3d2b849a5
This commit is contained in:
drh
2001-10-13 02:59:08 +00:00
parent 99fcd718e1
commit bf4133cba1
15 changed files with 350 additions and 116 deletions

View File

@ -25,7 +25,7 @@
** ROLLBACK
** PRAGMA
**
** $Id: build.c,v 1.48 2001/10/13 01:06:48 drh Exp $
** $Id: build.c,v 1.49 2001/10/13 02:59:09 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -1081,12 +1081,14 @@ ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
return pList;
}
}
i = pList->nExpr++;
pList->a[i].pExpr = pExpr;
pList->a[i].zName = 0;
if( pName ){
sqliteSetNString(&pList->a[i].zName, pName->z, pName->n, 0);
sqliteDequote(pList->a[i].zName);
if( pExpr ){
i = pList->nExpr++;
pList->a[i].pExpr = pExpr;
pList->a[i].zName = 0;
if( pName ){
sqliteSetNString(&pList->a[i].zName, pName->z, pName->n, 0);
sqliteDequote(pList->a[i].zName);
}
}
return pList;
}

View 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.30 2001/10/13 01:06:48 drh Exp $
** $Id: expr.c,v 1.31 2001/10/13 02:59:09 drh Exp $
*/
#include "sqliteInt.h"
@ -335,14 +335,16 @@ int sqliteFuncId(Token *pToken){
int len;
int id;
} 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},
{ "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 },
{ "abs", 3, FN_Abs },
{ "round", 5, FN_Round },
};
int i;
for(i=0; i<ArraySize(aFunc); i++){
@ -401,17 +403,23 @@ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
is_agg = 1;
break;
}
case FN_Abs:
case FN_Length: {
too_few_args = n<1;
too_many_args = n>1;
break;
}
case FN_Round: {
too_few_args = n<1;
too_many_args = n>2;
break;
}
case FN_Substr: {
too_few_args = n<3;
too_many_args = n>3;
break;
}
/* The "fcnt(*)" function always returns the number of fetch
/* The "fcnt(*)" function always returns the number of OP_MoveTo
** 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
@ -496,6 +504,12 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
case TK_NOTNULL: op = OP_NotNull; break;
case TK_NOT: op = OP_Not; break;
case TK_UMINUS: op = OP_Negative; break;
case TK_BITAND: op = OP_BitAnd; break;
case TK_BITOR: op = OP_BitOr; break;
case TK_BITNOT: op = OP_BitNot; break;
case TK_LSHIFT: op = OP_ShiftLeft; break;
case TK_RSHIFT: op = OP_ShiftRight; break;
case TK_REM: op = OP_Remainder; break;
default: break;
}
switch( pExpr->op ){
@ -534,12 +548,22 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
case TK_PLUS:
case TK_STAR:
case TK_MINUS:
case TK_REM:
case TK_BITAND:
case TK_BITOR:
case TK_SLASH: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
sqliteVdbeAddOp(v, op, 0, 0);
break;
}
case TK_LSHIFT:
case TK_RSHIFT: {
sqliteExprCode(pParse, pExpr->pRight);
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, op, 0, 0);
break;
}
case TK_CONCAT: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
@ -580,6 +604,7 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
}
/* Fall through into TK_NOT */
}
case TK_BITNOT:
case TK_NOT: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, op, 0, 0);
@ -625,6 +650,21 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
}
break;
}
case FN_Abs: {
sqliteExprCode(pParse, pList->a[0].pExpr);
sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
break;
}
case FN_Round: {
if( pList->nExpr==2 ){
sqliteExprCode(pParse, pList->a[1].pExpr);
}else{
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
}
sqliteExprCode(pParse, pList->a[0].pExpr);
sqliteVdbeAddOp(v, OP_Precision, 0, 0);
break;
}
case FN_Length: {
sqliteExprCode(pParse, pList->a[0].pExpr);
sqliteVdbeAddOp(v, OP_Strlen, 0, 0);

View 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.36 2001/10/12 17:30:05 drh Exp $
** @(#) $Id: parse.y,v 1.37 2001/10/13 02:59:09 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@ -331,7 +331,7 @@ inscollist(A) ::= ids(Y). {A = sqliteIdListAppend(0,&Y);}
%left GT GE LT LE.
%left BITAND BITOR LSHIFT RSHIFT.
%left PLUS MINUS.
%left STAR SLASH MOD.
%left STAR SLASH REM.
%left CONCAT.
%right UMINUS BITNOT.
@ -385,7 +385,7 @@ expr(A) ::= expr(X) PLUS expr(Y). {A = sqliteExpr(TK_PLUS, X, Y, 0);}
expr(A) ::= expr(X) MINUS expr(Y). {A = sqliteExpr(TK_MINUS, X, Y, 0);}
expr(A) ::= expr(X) STAR expr(Y). {A = sqliteExpr(TK_STAR, X, Y, 0);}
expr(A) ::= expr(X) SLASH expr(Y). {A = sqliteExpr(TK_SLASH, X, Y, 0);}
expr(A) ::= expr(X) MOD expr(Y). {A = sqliteExpr(TK_MOD, X, Y, 0);}
expr(A) ::= expr(X) REM expr(Y). {A = sqliteExpr(TK_REM, X, Y, 0);}
expr(A) ::= expr(X) CONCAT expr(Y). {A = sqliteExpr(TK_CONCAT, X, Y, 0);}
expr(A) ::= expr(X) ISNULL(E). {
A = sqliteExpr(TK_ISNULL, X, 0, 0);

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.60 2001/10/12 17:30:05 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.61 2001/10/13 02:59:09 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
@ -117,21 +117,8 @@ extern int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */
#define FN_Fcnt 6
#define FN_Length 7
#define FN_Substr 8
#if 0
#define FN_Abs 9
#define FN_Ceil 10
#define FN_Floor 11
#define FN_Frac 12
#define FN_Sin 13
#define FN_Cos 14
#define FN_Tan 15
#define FN_Asin 16
#define FN_Acos 17
#define FN_Atan 18
#define FN_Exp 19
#define FN_Ln 20
#define FN_Pow 21
#endif
#define FN_Round 10
/*
** Forward references to structures

View File

@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.26 2001/10/09 04:19:47 drh Exp $
** $Id: tokenize.c,v 1.27 2001/10/13 02:59:09 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -185,6 +185,10 @@ int sqliteGetToken(const char *z, int *tokenType){
*tokenType = TK_SLASH;
return 1;
}
case '%': {
*tokenType = TK_REM;
return 1;
}
case '=': {
*tokenType = TK_EQ;
return 1 + (z[1]=='=');
@ -196,6 +200,9 @@ int sqliteGetToken(const char *z, int *tokenType){
}else if( z[1]=='>' ){
*tokenType = TK_NE;
return 2;
}else if( z[1]=='<' ){
*tokenType = TK_LSHIFT;
return 2;
}else{
*tokenType = TK_LT;
return 1;
@ -205,6 +212,9 @@ int sqliteGetToken(const char *z, int *tokenType){
if( z[1]=='=' ){
*tokenType = TK_GE;
return 2;
}else if( z[1]=='>' ){
*tokenType = TK_RSHIFT;
return 2;
}else{
*tokenType = TK_GT;
return 1;
@ -221,7 +231,7 @@ int sqliteGetToken(const char *z, int *tokenType){
}
case '|': {
if( z[1]!='|' ){
*tokenType = TK_ILLEGAL;
*tokenType = TK_BITOR;
return 1;
}else{
*tokenType = TK_CONCAT;
@ -232,6 +242,14 @@ int sqliteGetToken(const char *z, int *tokenType){
*tokenType = TK_COMMA;
return 1;
}
case '&': {
*tokenType = TK_BITAND;
return 1;
}
case '~': {
*tokenType = TK_BITNOT;
return 1;
}
case '\'': case '"': {
int delim = z[0];
for(i=1; z[i]; i++){

View File

@ -30,7 +30,7 @@
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.83 2001/10/13 01:06:48 drh Exp $
** $Id: vdbe.c,v 1.84 2001/10/13 02:59:09 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -814,7 +814,9 @@ static char *zOpName[] = { 0,
"ColumnName", "Callback", "Integer", "String",
"Null", "Pop", "Dup", "Pull",
"Add", "AddImm", "Subtract", "Multiply",
"Divide", "Min", "Max", "Like",
"Divide", "Remainder", "BitAnd", "BitOr",
"BitNot", "ShiftLeft", "ShiftRight", "AbsValue",
"Precision", "Min", "Max", "Like",
"Glob", "Eq", "Ne", "Lt",
"Le", "Gt", "Ge", "IsNull",
"NotNull", "Negative", "And", "Or",
@ -1322,10 +1324,20 @@ case OP_Concat: {
** is a string then it is converted to a double using the atof()
** function before the division. Division by zero returns NULL.
*/
/* Opcode: Remainder * * *
**
** Pop the top two elements from the stack, divide the
** first (what was on top of the stack) from the second (the
** next on stack)
** and push the remainder after division onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the division. Division by zero returns NULL.
*/
case OP_Add:
case OP_Subtract:
case OP_Multiply:
case OP_Divide: {
case OP_Divide:
case OP_Remainder: {
int tos = p->tos;
int nos = tos - 1;
VERIFY( if( nos<0 ) goto not_enough_stack; )
@ -1337,11 +1349,16 @@ case OP_Divide: {
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
case OP_Multiply: b *= a; break;
default: {
case OP_Divide: {
if( a==0 ) goto divide_by_zero;
b /= a;
break;
}
default: {
if( a==0 ) goto divide_by_zero;
b %= a;
break;
}
}
POPSTACK;
Release(p, nos);
@ -1357,11 +1374,18 @@ case OP_Divide: {
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
case OP_Multiply: b *= a; break;
default: {
case OP_Divide: {
if( a==0.0 ) goto divide_by_zero;
b /= a;
break;
}
default: {
int ia = a;
int ib = b;
if( ia==0.0 ) goto divide_by_zero;
b = ib % ia;
break;
}
}
POPSTACK;
Release(p, nos);
@ -1377,6 +1401,37 @@ divide_by_zero:
break;
}
/*
** Opcode: Precision * * *
**
** The top of stack is a floating-point number and the next on stack is
** an integer. Truncate the floating-point number to a number of digits
** specified by the integer and push the floating-point number back onto
** the stack.
*/
case OP_Precision: {
int tos = p->tos;
int nos = tos - 1;
int nDigit;
double v;
char zBuf[100];
VERIFY( if( nos<0 ) goto not_enough_stack; )
Realify(p, tos);
Integerify(p, nos);
nDigit = aStack[nos].i;
if( nDigit<0 ) nDigit = 0;
if( nDigit>30 ) nDigit = 30;
v = aStack[tos].r;
sprintf(zBuf, "%.*f", nDigit, v);
POPSTACK;
Release(p, nos);
zStack[nos] = sqliteStrDup(zBuf);
aStack[nos].n = strlen(zStack[tos]) + 1;
aStack[nos].flags = STK_Str | STK_Dyn;
break;
}
/* Opcode: Max * * *
**
** Pop the top two elements from the stack then push back the
@ -1455,6 +1510,56 @@ case OP_Min: {
break;
}
/* Opcode: BitAnd * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the bit-wise AND of the
** two elements.
*/
/* Opcode: BitOr * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the bit-wise OR of the
** two elements.
*/
/* Opcode: ShiftLeft * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the top element shifted
** left by N bits where N is the second element on the stack.
*/
/* Opcode: ShiftRight * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the top element shifted
** right by N bits where N is the second element on the stack.
*/
case OP_BitAnd:
case OP_BitOr:
case OP_ShiftLeft:
case OP_ShiftRight: {
int tos = p->tos;
int nos = tos - 1;
int a, b;
VERIFY( if( nos<0 ) goto not_enough_stack; )
Integerify(p, tos);
Integerify(p, nos);
a = aStack[tos].i;
b = aStack[nos].i;
switch( pOp->opcode ){
case OP_BitAnd: a &= b; break;
case OP_BitOr: a |= b; break;
case OP_ShiftLeft: a <<= b; break;
case OP_ShiftRight: a >>= b; break;
default: /* CANT HAPPEN */ break;
}
POPSTACK;
Release(p, nos);
aStack[nos].i = a;
aStack[nos].flags = STK_Int;
break;
}
/* Opcode: AddImm P1 * *
**
** Add the value P1 to whatever is on top of the stack.
@ -1633,21 +1738,33 @@ case OP_Or: {
** Treat the top of the stack as a numeric quantity. Replace it
** with its additive inverse.
*/
case OP_Negative: {
/* Opcode: AbsValue * * *
**
** Treat the top of the stack as a numeric quantity. Replace it
** with its absolute value.
*/
case OP_Negative:
case OP_AbsValue: {
int tos = p->tos;
VERIFY( if( tos<0 ) goto not_enough_stack; )
if( aStack[tos].flags & STK_Real ){
Release(p, tos);
aStack[tos].r = -aStack[tos].r;
if( pOp->opcode==OP_Negative || aStack[tos].r<0.0 ){
aStack[tos].r = -aStack[tos].r;
}
aStack[tos].flags = STK_Real;
}else if( aStack[tos].flags & STK_Int ){
Release(p, tos);
aStack[tos].i = -aStack[tos].i;
if( pOp->opcode==OP_Negative || aStack[tos].i<0 ){
aStack[tos].i = -aStack[tos].i;
}
aStack[tos].flags = STK_Int;
}else{
Realify(p, tos);
Release(p, tos);
aStack[tos].r = -aStack[tos].r;
if( pOp->opcode==OP_Negative || aStack[tos].r<0.0 ){
aStack[tos].r = -aStack[tos].r;
}
aStack[tos].flags = STK_Real;
}
break;
@ -1668,6 +1785,21 @@ case OP_Not: {
break;
}
/* Opcode: * * *
**
** Interpret the top of the stack as an value. Replace it
** with its ones-complement.
*/
case OP_BitNot: {
int tos = p->tos;
VERIFY( if( p->tos<0 ) goto not_enough_stack; )
Integerify(p, tos);
Release(p, tos);
aStack[tos].i = ~aStack[tos].i;
aStack[tos].flags = STK_Int;
break;
}
/* Opcode: Noop * * *
**
** Do nothing. This instruction is often useful as a jump

View File

@ -15,7 +15,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.28 2001/10/13 01:06:49 drh Exp $
** $Id: vdbe.h,v 1.29 2001/10/13 02:59:09 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@ -168,38 +168,37 @@ typedef struct VdbeOp VdbeOp;
#define OP_Subtract 83
#define OP_Multiply 84
#define OP_Divide 85
#define OP_Remainder
#define OP_BitAnd
#define OP_BitOr
#define OP_BitNot
#define OP_ShiftLeft
#define OP_ShiftRight
#define OP_Power
#define OP_Exp
#define OP_Log
#define OP_Min 86
#define OP_Max 87
#define OP_Like 88
#define OP_Glob 89
#define OP_Eq 90
#define OP_Ne 91
#define OP_Lt 92
#define OP_Le 93
#define OP_Gt 94
#define OP_Ge 95
#define OP_IsNull 96
#define OP_NotNull 97
#define OP_Negative 98
#define OP_And 99
#define OP_Or 100
#define OP_Not 101
#define OP_Concat 102
#define OP_Noop 103
#define OP_Remainder 86
#define OP_BitAnd 87
#define OP_BitOr 88
#define OP_BitNot 89
#define OP_ShiftLeft 90
#define OP_ShiftRight 91
#define OP_AbsValue 92
#define OP_Precision 93
#define OP_Min 94
#define OP_Max 95
#define OP_Like 96
#define OP_Glob 97
#define OP_Eq 98
#define OP_Ne 99
#define OP_Lt 100
#define OP_Le 101
#define OP_Gt 102
#define OP_Ge 103
#define OP_IsNull 104
#define OP_NotNull 105
#define OP_Negative 106
#define OP_And 107
#define OP_Or 108
#define OP_Not 109
#define OP_Concat 110
#define OP_Noop 111
#define OP_Strlen 104
#define OP_Substr 105
#define OP_Strlen 112
#define OP_Substr 113
#define OP_MAX 105
#define OP_MAX 113
/*
** Prototypes for the VDBE interface. See comments on the implementation