aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2005-11-01 15:48:24 +0000
committerdrh <drh@noemail.net>2005-11-01 15:48:24 +0000
commit8df447f0e6aff82ea4261507f29ee6ab724cb489 (patch)
tree43a088577d54400a5bc7b697a53be5bbfe05cc94 /src
parentb12761293300b49d676017f5576fdd6866f9eb8e (diff)
downloadsqlite-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.c3
-rw-r--r--src/build.c14
-rw-r--r--src/expr.c23
-rw-r--r--src/insert.c4
-rw-r--r--src/sqliteInt.h6
-rw-r--r--src/vdbe.c38
-rw-r--r--src/vdbeInt.h1
-rw-r--r--src/vdbemem.c26
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;
}