diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 59 | ||||
-rw-r--r-- | src/sqliteInt.h | 9 | ||||
-rw-r--r-- | src/util.c | 79 | ||||
-rw-r--r-- | src/vdbe.c | 48 | ||||
-rw-r--r-- | src/vdbeaux.c | 12 | ||||
-rw-r--r-- | src/where.c | 9 |
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); |