diff options
author | drh <drh@noemail.net> | 2005-11-01 15:48:24 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2005-11-01 15:48:24 +0000 |
commit | 8df447f0e6aff82ea4261507f29ee6ab724cb489 (patch) | |
tree | 43a088577d54400a5bc7b697a53be5bbfe05cc94 /src | |
parent | b12761293300b49d676017f5576fdd6866f9eb8e (diff) | |
download | sqlite-8df447f0e6aff82ea4261507f29ee6ab724cb489.tar.gz sqlite-8df447f0e6aff82ea4261507f29ee6ab724cb489.zip |
Omit the SQLITE_AFF_INTEGER type affinity. All numeric values are now
of type real, though an integer representation is still sometimes used
internally for efficiency. (CVS 2753)
FossilOrigin-Name: e0d6f61c7de2c03b8fd17ef37cf1a0add36ee618
Diffstat (limited to 'src')
-rw-r--r-- | src/analyze.c | 3 | ||||
-rw-r--r-- | src/build.c | 14 | ||||
-rw-r--r-- | src/expr.c | 23 | ||||
-rw-r--r-- | src/insert.c | 4 | ||||
-rw-r--r-- | src/sqliteInt.h | 6 | ||||
-rw-r--r-- | src/vdbe.c | 38 | ||||
-rw-r--r-- | src/vdbeInt.h | 1 | ||||
-rw-r--r-- | src/vdbemem.c | 26 |
8 files changed, 59 insertions, 56 deletions
diff --git a/src/analyze.c b/src/analyze.c index 67d80d534..59749704d 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.9 2005/09/20 17:42:23 drh Exp $ +** @(#) $Id: analyze.c,v 1.10 2005/11/01 15:48:24 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -188,6 +188,7 @@ static void analyzeOneTable( sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0); sqlite3VdbeAddOp(v, OP_Divide, 0, 0); + sqlite3VdbeAddOp(v, OP_ToInt, 0, 0); if( i==nCol-1 ){ sqlite3VdbeAddOp(v, OP_Concat, nCol*2-1, 0); }else{ diff --git a/src/build.c b/src/build.c index 9857a8e15..69a652b33 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.351 2005/09/20 17:42:23 drh Exp $ +** $Id: build.c,v 1.352 2005/11/01 15:48:24 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -882,7 +882,7 @@ void sqlite3AddNotNull(Parse *pParse, int onError){ ** found, the corresponding affinity is returned. If zType contains ** more than one of the substrings, entries toward the top of ** the table take priority. For example, if zType is 'BLOBINT', -** SQLITE_AFF_INTEGER is returned. +** SQLITE_AFF_NUMERIC is returned. ** ** Substring | Affinity ** -------------------------------- @@ -894,8 +894,12 @@ void sqlite3AddNotNull(Parse *pParse, int onError){ ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. +** +** The SQLITE_AFF_INTEGER type is only returned if useIntType is true. +** If useIntType is false, then SQLITE_AFF_INTEGER is reported back +** as SQLITE_AFF_NUMERIC */ -char sqlite3AffinityType(const Token *pType){ +char sqlite3AffinityType(const Token *pType, int useIntType){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; const unsigned char *zIn = pType->z; @@ -914,7 +918,7 @@ char sqlite3AffinityType(const Token *pType){ && aff==SQLITE_AFF_NUMERIC ){ aff = SQLITE_AFF_NONE; }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ - aff = SQLITE_AFF_INTEGER; + aff = useIntType ? SQLITE_AFF_INTEGER : SQLITE_AFF_NUMERIC; break; } } @@ -942,7 +946,7 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){ pCol = &p->aCol[i]; sqliteFree(pCol->zType); pCol->zType = sqlite3NameFromToken(pType); - pCol->affinity = sqlite3AffinityType(pType); + pCol->affinity = sqlite3AffinityType(pType, 0); } /* diff --git a/src/expr.c b/src/expr.c index f1eae86d6..b915059d4 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.231 2005/10/06 16:53:15 drh Exp $ +** $Id: expr.c,v 1.232 2005/11/01 15:48:24 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -43,7 +43,7 @@ char sqlite3ExprAffinity(Expr *pExpr){ } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ - return sqlite3AffinityType(&pExpr->token); + return sqlite3AffinityType(&pExpr->token, 0); } #endif return pExpr->affinity; @@ -75,12 +75,10 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ char aff1 = sqlite3ExprAffinity(pExpr); if( aff1 && aff2 ){ - /* Both sides of the comparison are columns. If one has numeric or - ** integer affinity, use that. Otherwise use no affinity. + /* Both sides of the comparison are columns. If one has numeric + ** affinity, use that. Otherwise use no affinity. */ - if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){ - return SQLITE_AFF_INTEGER; - }else if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){ + if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){ return SQLITE_AFF_NUMERIC; }else{ return SQLITE_AFF_NONE; @@ -89,7 +87,6 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ /* Neither side of the comparison is a column. Compare the ** results directly. */ - /* return SQLITE_AFF_NUMERIC; // Ticket #805 */ return SQLITE_AFF_NONE; }else{ /* One side is a column, the other is not. Use the columns affinity. */ @@ -129,11 +126,7 @@ static char comparisonAffinity(Expr *pExpr){ */ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ char aff = comparisonAffinity(pExpr); - return - (aff==SQLITE_AFF_NONE) || - (aff==SQLITE_AFF_NUMERIC && idx_affinity==SQLITE_AFF_INTEGER) || - (aff==SQLITE_AFF_INTEGER && idx_affinity==SQLITE_AFF_NUMERIC) || - (aff==idx_affinity); + return (aff==SQLITE_AFF_NONE) || (aff==idx_affinity); } /* @@ -944,7 +937,7 @@ static int lookupName( if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){ cnt = 1; pExpr->iColumn = -1; - pExpr->affinity = SQLITE_AFF_INTEGER; + pExpr->affinity = SQLITE_AFF_NUMERIC; } /* @@ -1524,7 +1517,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ /* Expressions of the form: CAST(pLeft AS token) */ int aff, op; sqlite3ExprCode(pParse, pExpr->pLeft); - aff = sqlite3AffinityType(&pExpr->token); + aff = sqlite3AffinityType(&pExpr->token, 1); switch( aff ){ case SQLITE_AFF_INTEGER: op = OP_ToInt; break; case SQLITE_AFF_NUMERIC: op = OP_ToNumeric; break; diff --git a/src/insert.c b/src/insert.c index e19aa7da1..dcc57d571 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.143 2005/09/20 17:42:23 drh Exp $ +** $Id: insert.c,v 1.144 2005/11/01 15:48:24 drh Exp $ */ #include "sqliteInt.h" @@ -24,7 +24,6 @@ ** Character Column affinity ** ------------------------------ ** 'n' NUMERIC -** 'i' INTEGER ** 't' TEXT ** 'o' NONE */ @@ -62,7 +61,6 @@ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ ** Character Column affinity ** ------------------------------ ** 'n' NUMERIC -** 'i' INTEGER ** 't' TEXT ** 'o' NONE */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7b4f360b6..51d1ce76c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.423 2005/10/13 02:09:50 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.424 2005/11/01 15:48:24 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -585,8 +585,8 @@ struct CollSeq { /* ** Column affinity types. */ -#define SQLITE_AFF_INTEGER 'i' #define SQLITE_AFF_NUMERIC 'n' +#define SQLITE_AFF_INTEGER 'i' /* Used for CAST operators only */ #define SQLITE_AFF_TEXT 't' #define SQLITE_AFF_NONE 'o' @@ -1646,7 +1646,7 @@ void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); const char *sqlite3TestErrorName(int); CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int); -char sqlite3AffinityType(const Token*); +char sqlite3AffinityType(const Token*, int); void sqlite3Analyze(Parse*, Token*, Token*); int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); diff --git a/src/vdbe.c b/src/vdbe.c index 09cac0466..30f57be18 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.494 2005/10/29 15:48:31 drh Exp $ +** $Id: vdbe.c,v 1.495 2005/11/01 15:48:24 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -194,8 +194,6 @@ static Cursor *allocateCursor(Vdbe *p, int iCur){ ** SQLITE_AFF_NUMERIC ** SQLITE_AFF_TEXT ** SQLITE_AFF_NONE -** SQLITE_AFF_INTEGER -** */ static void applyAffinity(Mem *pRec, char affinity, u8 enc){ if( affinity==SQLITE_AFF_NONE ){ @@ -224,16 +222,8 @@ static void applyAffinity(Mem *pRec, char affinity, u8 enc){ Integerify(pRec); } } - } - - if( affinity==SQLITE_AFF_INTEGER ){ - /* For INTEGER affinity, try to convert a real value to an int */ - if( (pRec->flags&MEM_Real) && !(pRec->flags&MEM_Int) ){ - pRec->i = pRec->r; - if( ((double)pRec->i)==pRec->r ){ - pRec->flags |= MEM_Int; - } - } + }else if( pRec->flags & MEM_Real ){ + sqlite3VdbeIntegerAffinity(pRec); } } } @@ -645,6 +635,7 @@ case OP_Real: { /* same as TK_FLOAT, */ pTos->r = sqlite3VdbeRealValue(pTos); pTos->flags |= MEM_Real; sqlite3VdbeChangeEncoding(pTos, db->enc); + sqlite3VdbeIntegerAffinity(pTos); break; } @@ -1030,6 +1021,7 @@ case OP_Remainder: { /* same as TK_REM, no-push */ case OP_Multiply: b *= a; break; case OP_Divide: { if( a==0 ) goto divide_by_zero; + if( b%a!=0 ) goto floating_point_divide; b /= a; break; } @@ -1046,6 +1038,7 @@ case OP_Remainder: { /* same as TK_REM, no-push */ pTos->flags = MEM_Int; }else{ double a, b; + floating_point_divide: a = sqlite3VdbeRealValue(pTos); b = sqlite3VdbeRealValue(pNos); switch( pOp->opcode ){ @@ -1070,6 +1063,7 @@ case OP_Remainder: { /* same as TK_REM, no-push */ Release(pTos); pTos->r = b; pTos->flags = MEM_Real; + sqlite3VdbeIntegerAffinity(pTos); } break; @@ -1267,7 +1261,7 @@ case OP_AddImm: { /* no-push */ case OP_ForceInt: { /* no-push */ i64 v; assert( pTos>=p->aStack ); - applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc); + applyAffinity(pTos, SQLITE_AFF_NUMERIC, db->enc); if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){ Release(pTos); pTos--; @@ -1301,7 +1295,7 @@ case OP_ForceInt: { /* no-push */ */ case OP_MustBeInt: { /* no-push */ assert( pTos>=p->aStack ); - applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc); + applyAffinity(pTos, SQLITE_AFF_NUMERIC, db->enc); if( (pTos->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; @@ -1317,7 +1311,6 @@ case OP_MustBeInt: { /* no-push */ break; } -#ifndef SQLITE_OMIT_CAST /* Opcode: ToInt * * * ** ** Force the value on the top of the stack to be an integer. If @@ -1332,11 +1325,12 @@ case OP_ToInt: { /* no-push */ if( pTos->flags & MEM_Null ) break; assert( MEM_Str==(MEM_Blob>>3) ); pTos->flags |= (pTos->flags&MEM_Blob)>>3; - applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc); + applyAffinity(pTos, SQLITE_AFF_NUMERIC, db->enc); sqlite3VdbeMemIntegerify(pTos); break; } +#ifndef SQLITE_OMIT_CAST /* Opcode: ToNumeric * * * ** ** Force the value on the top of the stack to be numeric (either an @@ -1422,7 +1416,7 @@ case OP_ToBlob: { /* no-push */ ** 0x200 is set but is NULL when the 0x200 bit of P1 is clear. ** ** The least significant byte of P1 (mask 0xff) must be an affinity character - -** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values +** 'n', 't', or 'o' - or 0x00. An attempt is made to coerce both values ** according to the affinity before the comparison is made. If the byte is ** 0x00, then numeric affinity is used. ** @@ -1614,11 +1608,13 @@ case OP_Negative: /* same as TK_UMINUS, no-push */ case OP_AbsValue: { assert( pTos>=p->aStack ); if( pTos->flags & MEM_Real ){ + neg_abs_real_case: Release(pTos); if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ pTos->r = -pTos->r; } pTos->flags = MEM_Real; + sqlite3VdbeIntegerAffinity(pTos); }else if( pTos->flags & MEM_Int ){ Release(pTos); if( pOp->opcode==OP_Negative || pTos->i<0 ){ @@ -1629,10 +1625,7 @@ case OP_AbsValue: { /* Do nothing */ }else{ Realify(pTos); - if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ - pTos->r = -pTos->r; - } - pTos->flags = MEM_Real; + goto neg_abs_real_case; } break; } @@ -2083,7 +2076,6 @@ op_column_out: ** ** The mapping from character to affinity is as follows: ** 'n' = NUMERIC. -** 'i' = INTEGER. ** 't' = TEXT. ** 'o' = NONE. ** diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 1746ee561..e38f809e6 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -360,6 +360,7 @@ int sqlite3VdbeMemStringify(Mem*, int); i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); +void sqlite3VdbeIntegerAffinity(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); void sqlite3VdbeMemRelease(Mem *p); diff --git a/src/vdbemem.c b/src/vdbemem.c index 0b7e193be..7f40af63a 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -173,11 +173,11 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){ ** ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. */ - if( fg & MEM_Real ){ - sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r); - }else{ - assert( fg & MEM_Int ); + if( fg & MEM_Int ){ sqlite3_snprintf(NBFS, z, "%lld", pMem->i); + }else{ + assert( fg & MEM_Real ); + sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r); } pMem->n = strlen(z); pMem->z = z; @@ -300,13 +300,27 @@ double sqlite3VdbeRealValue(Mem *pMem){ } /* -** Convert pMem so that it is of type MEM_Real. Invalidate any -** prior representations. +** The MEM structure is already a MEM_Real. Try to also make it a +** MEM_Int if we can. +*/ +void sqlite3VdbeIntegerAffinity(Mem *pMem){ + assert( pMem->flags & MEM_Real ); + pMem->i = pMem->r; + if( ((double)pMem->i)==pMem->r ){ + pMem->flags |= MEM_Int; + } +} + + +/* +** Convert pMem so that it is of type MEM_Real and also MEM_Int if +** possible. Invalidate any prior representations. */ int sqlite3VdbeMemRealify(Mem *pMem){ pMem->r = sqlite3VdbeRealValue(pMem); sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Real; + sqlite3VdbeIntegerAffinity(pMem); return SQLITE_OK; } |