aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expr.c59
-rw-r--r--src/sqliteInt.h9
-rw-r--r--src/util.c79
-rw-r--r--src/vdbe.c48
-rw-r--r--src/vdbeaux.c12
-rw-r--r--src/where.c9
6 files changed, 131 insertions, 85 deletions
diff --git a/src/expr.c b/src/expr.c
index a0fff71d8..65821bd53 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -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.122 2004/05/18 10:06:25 danielk1977 Exp $
+** $Id: expr.c,v 1.123 2004/05/19 20:41:03 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -442,8 +442,7 @@ int sqlite3ExprIsConstant(Expr *p){
int sqlite3ExprIsInteger(Expr *p, int *pValue){
switch( p->op ){
case TK_INTEGER: {
- if( sqlite3FitsIn32Bits(p->token.z) ){
- *pValue = atoi(p->token.z);
+ if( sqlite3GetInt32(p->token.z, pValue) ){
return 1;
}
break;
@@ -453,8 +452,7 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
int n = p->token.n;
if( n>0 && z[0]=='-' ){ z++; n--; }
while( n>0 && *z && isdigit(*z) ){ z++; n--; }
- if( n==0 && sqlite3FitsIn32Bits(p->token.z) ){
- *pValue = atoi(p->token.z);
+ if( n==0 && sqlite3GetInt32(p->token.z, pValue) ){
return 1;
}
break;
@@ -1132,6 +1130,19 @@ int sqlite3ExprType(Expr *p){
}
/*
+** Generate an instruction that will put the integer describe by
+** text z[0..n-1] on the stack.
+*/
+static void codeInteger(Vdbe *v, const char *z, int n){
+ int i;
+ if( sqlite3GetInt32(z, &i) || (i=0, sqlite3FitsIn64Bits(z))!=0 ){
+ sqlite3VdbeOp3(v, OP_Integer, i, 0, z, n);
+ }else{
+ sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n);
+ }
+}
+
+/*
** Generate code into the current Vdbe to evaluate the given
** expression and leave the result on the top of stack.
*/
@@ -1162,6 +1173,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
case TK_LSHIFT: op = OP_ShiftLeft; break;
case TK_RSHIFT: op = OP_ShiftRight; break;
case TK_REM: op = OP_Remainder; break;
+ case TK_FLOAT: op = OP_Real; break;
+ case TK_STRING: op = OP_String; break;
default: break;
}
switch( pExpr->op ){
@@ -1175,18 +1188,13 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
}
break;
}
- case TK_STRING:
- case TK_FLOAT:
case TK_INTEGER: {
- if( pExpr->op==TK_INTEGER && sqlite3FitsIn32Bits(pExpr->token.z) ){
- sqlite3VdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0);
- }else if( pExpr->op==TK_FLOAT || pExpr->op==TK_INTEGER ){
- sqlite3VdbeAddOp(v, OP_Real, 0, 0);
- }else{
- sqlite3VdbeAddOp(v, OP_String, 0, 0);
- }
- assert( pExpr->token.z );
- sqlite3VdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
+ codeInteger(v, pExpr->token.z, pExpr->token.n);
+ break;
+ }
+ case TK_FLOAT:
+ case TK_STRING: {
+ sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n);
sqlite3VdbeDequoteP3(v, -1);
break;
}
@@ -1238,17 +1246,17 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
break;
}
case TK_UMINUS: {
- assert( pExpr->pLeft );
- if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){
- Token *p = &pExpr->pLeft->token;
+ Expr *pLeft = pExpr->pLeft;
+ assert( pLeft );
+ if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){
+ Token *p = &pLeft->token;
char *z = sqliteMalloc( p->n + 2 );
sprintf(z, "-%.*s", p->n, p->z);
- if( pExpr->pLeft->op==TK_INTEGER && sqlite3FitsIn32Bits(z) ){
- sqlite3VdbeAddOp(v, OP_Integer, atoi(z), 0);
+ if( pLeft->op==TK_FLOAT ){
+ sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1);
}else{
- sqlite3VdbeAddOp(v, OP_Real, 0, 0);
+ codeInteger(v, z, p->n+1);
}
- sqlite3VdbeChangeP3(v, -1, z, p->n+1);
sqliteFree(z);
break;
}
@@ -1289,7 +1297,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
/* FIX ME: The following is a temporary hack. */
if( 0==sqlite3StrNICmp(zId, "classof", nId) ){
assert( nExpr==1 );
- sqlite3VdbeOp3(v, OP_Class, nExpr, 0, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Class, nExpr, 0);
}else{
sqlite3VdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER);
}
@@ -1800,6 +1808,3 @@ FuncDef *sqlite3FindFunction(
}
return p;
}
-
-
-
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 9334083fb..afea0e465 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.237 2004/05/18 23:21:36 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.238 2004/05/19 20:41:03 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
@@ -478,6 +478,7 @@ struct Column {
*/
struct CollSeq {
char *zName; /* Name of the collating sequence */
+ u8 reverseOrder; /* Compare in reverse order. Used by OP_Sort only */
void *pUser; /* First argument to xCmp() */
int (*xCmp)(void*,int,const void*,int,const void*); /* Comparison function */
};
@@ -1312,8 +1313,9 @@ int sqlite3FixExprList(DbFixer*, ExprList*);
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
double sqlite3AtoF(const char *z, const char **);
char *sqlite3_snprintf(int,char*,const char*,...);
-int sqlite3FitsIn32Bits(const char *);
-
+int sqlite3GetInt32(const char *, int*);
+int sqlite3GetInt64(const char *, i64*);
+int sqlite3FitsIn64Bits(const char *);
unsigned char *sqlite3utf16to8(const void *pData, int N);
void *sqlite3utf8to16be(const unsigned char *pIn, int N);
void *sqlite3utf8to16le(const unsigned char *pIn, int N);
@@ -1330,3 +1332,4 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2);
char const *sqlite3AffinityString(char affinity);
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
char sqlite3ExprAffinity(Expr *pExpr);
+int sqlite3atoi64(const char*, i64*);
diff --git a/src/util.c b/src/util.c
index d37a56eb2..c677f6118 100644
--- a/src/util.c
+++ b/src/util.c
@@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.85 2004/05/19 10:34:57 danielk1977 Exp $
+** $Id: util.c,v 1.86 2004/05/19 20:41:03 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@@ -611,6 +611,38 @@ double sqlite3AtoF(const char *z, const char **pzEnd){
}
/*
+** Return TRUE if zNum is a 64-bit signed integer and write
+** the value of the integer into *pNum. If zNum is not an integer
+** or is an integer that is too large to be expressed with 64 bits,
+** then return false. If n>0 and the integer is string is not
+** exactly n bytes long, return false.
+**
+** When this routine was originally written it dealt with only
+** 32-bit numbers. At that time, it was much faster than the
+** atoi() library routine in RedHat 7.2.
+*/
+int sqlite3atoi64(const char *zNum, i64 *pNum){
+ i64 v = 0;
+ int neg;
+ int i, c;
+ if( *zNum=='-' ){
+ neg = 1;
+ zNum++;
+ }else if( *zNum=='+' ){
+ neg = 0;
+ zNum++;
+ }else{
+ neg = 0;
+ }
+ for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
+ v = v*10 + c - '0';
+ }
+ *pNum = neg ? -v : v;
+ return c==0 && i>0 &&
+ (i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0));
+}
+
+/*
** The string zNum represents an integer. There might be some other
** information following the integer too, but that part is ignored.
** If the integer that the prefix of zNum represents will fit in a
@@ -621,13 +653,55 @@ double sqlite3AtoF(const char *z, const char **pzEnd){
** 2147483648 will not fit in 32 bits. So it seems safer to return
** false.
*/
-int sqlite3FitsIn32Bits(const char *zNum){
+static int sqlite3FitsIn32Bits(const char *zNum){
int i, c;
if( *zNum=='-' || *zNum=='+' ) zNum++;
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0);
}
+/*
+** If zNum represents an integer that will fit in 32-bits, then set
+** *pValue to that integer and return true. Otherwise return false.
+*/
+int sqlite3GetInt32(const char *zNum, int *pValue){
+ if( sqlite3FitsIn32Bits(zNum) ){
+ *pValue = atoi(zNum);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+** The string zNum represents an integer. There might be some other
+** information following the integer too, but that part is ignored.
+** If the integer that the prefix of zNum represents will fit in a
+** 64-bit signed integer, return TRUE. Otherwise return FALSE.
+**
+** This routine returns FALSE for the string -9223372036854775808 even that
+** that number will, in theory fit in a 64-bit integer. Positive
+** 9223373036854775808 will not fit in 64 bits. So it seems safer to return
+** false.
+*/
+int sqlite3FitsIn64Bits(const char *zNum){
+ int i, c;
+ if( *zNum=='-' || *zNum=='+' ) zNum++;
+ for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
+ return i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0);
+}
+
+/*
+** If zNum represents an integer that will fit in 64-bits, then set
+** *pValue to that integer and return true. Otherwise return false.
+*/
+int sqlite3GetInt64(const char *zNum, i64 *pValue){
+ if( sqlite3FitsIn64Bits(zNum) ){
+ sqlite3atoi64(zNum, pValue);
+ return 1;
+ }
+ return 0;
+}
+
/* This comparison routine is what we use for comparison operations
** between numeric values in an SQL expression. "Numeric" is a little
** bit misleading here. What we mean is that the strings have a
@@ -1180,4 +1254,3 @@ int sqlite3VarintLen(u64 v){
}while( v!=0 && i<9 );
return i;
}
-
diff --git a/src/vdbe.c b/src/vdbe.c
index 688670553..5bcaea930 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.304 2004/05/19 14:56:57 drh Exp $
+** $Id: vdbe.c,v 1.305 2004/05/19 20:41:03 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -277,36 +277,6 @@ static void popStack(Mem **ppTos, int N){
}
/*
-** Return TRUE if zNum is a 32-bit signed integer and write
-** the value of the integer into *pNum. If zNum is not an integer
-** or is an integer that is too large to be expressed with just 32
-** bits, then return false.
-**
-** Under Linux (RedHat 7.2) this routine is much faster than atoi()
-** for converting strings into integers.
-*/
-static int toInt(const char *zNum, i64 *pNum){
- i64 v = 0;
- int neg;
- int i, c;
- if( *zNum=='-' ){
- neg = 1;
- zNum++;
- }else if( *zNum=='+' ){
- neg = 0;
- zNum++;
- }else{
- neg = 0;
- }
- for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
- v = v*10 + c - '0';
- }
- *pNum = neg ? -v : v;
- return c==0 && i>0 &&
- (i<10 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0));
-}
-
-/*
** Convert the given stack entity into a integer if it isn't one
** already.
**
@@ -319,7 +289,7 @@ static void hardIntegerify(Mem *pStack){
pStack->i = (int)pStack->r;
Release(pStack);
}else if( pStack->flags & MEM_Str ){
- toInt(pStack->z, &pStack->i);
+ sqlite3atoi64(pStack->z, &pStack->i);
Release(pStack);
}else{
pStack->i = 0;
@@ -792,6 +762,7 @@ case OP_Halt: {
**
** The integer value P1 is pushed onto the stack. If P3 is not zero
** then it is assumed to be a string representation of the same integer.
+** If P1 is zero and P3 is not zero, then the value is derived from P3.
*/
case OP_Integer: {
pTos++;
@@ -801,6 +772,9 @@ case OP_Integer: {
pTos->z = pOp->p3;
pTos->flags |= MEM_Str | MEM_Static;
pTos->n = strlen(pOp->p3)+1;
+ if( pTos->i==0 ){
+ sqlite3GetInt64(pTos->z, &pTos->i);
+ }
}
break;
}
@@ -1417,7 +1391,7 @@ case OP_MustBeInt: {
pTos->i = i;
}else if( pTos->flags & MEM_Str ){
i64 v;
- if( !toInt(pTos->z, &v) ){
+ if( !sqlite3atoi64(pTos->z, &v) ){
double r;
if( !sqlite3IsNumber(pTos->z, 0) ){
goto mismatch;
@@ -3334,9 +3308,11 @@ case OP_SetCounts: {
*/
case OP_KeyAsData: {
int i = pOp->p1;
+ Cursor *pC;
assert( i>=0 && i<p->nCursor );
- p->apCsr[i]->keyAsData = pOp->p2;
- sqlite3BtreeSetCompare(p->apCsr[i]->pCursor, sqlite3VdbeRowCompare, p->apCsr[i]);
+ pC = p->apCsr[i];
+ pC->keyAsData = pOp->p2;
+ sqlite3BtreeSetCompare(pC->pCursor, sqlite3VdbeRowCompare, pC);
break;
}
@@ -4035,7 +4011,7 @@ case OP_IntegrityCk: {
if( aRoot==0 ) goto no_mem;
for(j=0, i=sqliteHashFirst(&pSet->hash); i; i=sqliteHashNext(i), j++){
i64 root64;
- toInt((char*)sqliteHashKey(i), &root64);
+ sqlite3atoi64((char*)sqliteHashKey(i), &root64);
aRoot[j] = root64;
}
aRoot[j] = 0;
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 9c4f70235..a8f04a5e9 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -1387,13 +1387,13 @@ int sqlite3MemCompare(Mem *pMem1, Mem *pMem2){
** if both values are integers.
*/
if( combined_flags&(MEM_Int|MEM_Real) ){
+ i64 diff;
if( !(pMem1->flags&(MEM_Int|MEM_Real)) ){
return 1;
}
if( !(pMem2->flags&(MEM_Int|MEM_Real)) ){
return -1;
}
-
if( combined_flags&MEM_Real ){
if( pMem1->flags&MEM_Int ){
pMem1->r = pMem1->i;
@@ -1405,8 +1405,8 @@ int sqlite3MemCompare(Mem *pMem1, Mem *pMem2){
if( pMem1->r > pMem2->r ) return 1;
return 0;
}
-
- return (pMem1->i - pMem2->i);
+ diff = pMem1->i - pMem2->i;
+ return diff<0 ? -1 : diff==0 ? 0 : +1;
}
rc = (pMem2->flags&MEM_Null) - (pMem1->flags&MEM_Null);
@@ -1667,12 +1667,6 @@ int sqlite3VdbeIdxKeyCompare(
len = nCellKey-2;
while( pCellKey[len] && --len );
-#if 0
- if( ignorerowid ){
- nKey--;
- while( pKey[nKey] && --nKey );
- }
-#endif
*res = sqlite3VdbeKeyCompare(pC, len, pCellKey, nKey, pKey);
if( freeCellKey ){
diff --git a/src/where.c b/src/where.c
index cc8ac97dd..af4fa53a9 100644
--- a/src/where.c
+++ b/src/where.c
@@ -12,7 +12,7 @@
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
-** $Id: where.c,v 1.98 2004/05/19 14:56:57 drh Exp $
+** $Id: where.c,v 1.99 2004/05/19 20:41:04 drh Exp $
*/
#include "sqliteInt.h"
@@ -746,7 +746,6 @@ WhereInfo *sqlite3WhereBegin(
** refer to the index use the "==" or "IN" operators.
*/
int start;
- int testOp;
int nColumn = (pLevel->score+4)/8;
brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
@@ -824,11 +823,7 @@ WhereInfo *sqlite3WhereBegin(
/* Scan in the forward order */
sqlite3VdbeAddOp(v, OP_MoveGe, pLevel->iCur, brk);
start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
- if( nColumn==pIdx->nColumn || 0 ){
- sqlite3VdbeAddOp(v, OP_IdxGT, pLevel->iCur, brk);
- }else{
- sqlite3VdbeOp3(v, OP_IdxGE, pLevel->iCur, brk, "+", P3_STATIC);
- }
+ sqlite3VdbeOp3(v, OP_IdxGE, pLevel->iCur, brk, "+", P3_STATIC);
pLevel->op = OP_Next;
}
sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);