From: drh Date: Thu, 18 Sep 2014 17:52:15 +0000 (+0000) Subject: Merge the Mem.r value into the MemValue union as Mem.u.r. Hence, a Mem can X-Git-Tag: version-3.8.7~101 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=74eaba4de25d955314df279e5ca27aa24f2698ea;p=thirdparty%2Fsqlite.git Merge the Mem.r value into the MemValue union as Mem.u.r. Hence, a Mem can now store an integer or a real but not both at the same time. Strings are still stored in a separate element Mem.z, for now. FossilOrigin-Name: 4c8c89d7e62aecfe2eb735f7bb114aed6b452847 --- diff --git a/manifest b/manifest index 8cf00918c0..4bfcb72630 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\simprovement\sfor\saffinity\stransformations\son\scomparison\soperators. -D 2014-09-18T16:28:59.796 +C Merge\sthe\sMem.r\svalue\sinto\sthe\sMemValue\sunion\sas\sMem.u.r.\s\sHence,\sa\sMem\scan\nnow\sstore\san\sinteger\sor\sa\sreal\sbut\snot\sboth\sat\sthe\ssame\stime.\s\sStrings\sare\nstill\sstored\sin\sa\sseparate\selement\sMem.z,\sfor\snow. +D 2014-09-18T17:52:15.374 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -288,15 +288,15 @@ F src/update.c 729f6f18fc27740591d085e1172cebe311144bf0 F src/utf.c 8f634b93d41c089029dd503161a7d3e685d59a9c F src/util.c 4006c01772bd8d8ac4306d523bbcee41d3e392d8 F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a -F src/vdbe.c b00ffadc43a588b02ca2b60b9128338a6f4efcba +F src/vdbe.c 17f285ff89d73b6af5bd1fc90c0943341f4003d5 F src/vdbe.h 09f5b4e3719fa454f252322b1cdab5cf1f361327 -F src/vdbeInt.h f90b0de6153f50de630a5a113537efb47083812f -F src/vdbeapi.c c02242df5e9e8d1001e0086f405953833f9c426b -F src/vdbeaux.c 9ac63bc59d2783df77e591e4c4fa8c1153a07eab +F src/vdbeInt.h 45a0b4c5e4b38a2ff8af05102d45e7fa2e6c4439 +F src/vdbeapi.c 88929e02676fdbd5f436fcfd63fa0d371756a7ce +F src/vdbeaux.c ac3188f182f25eac58923b1a3c0840c69949ed28 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 -F src/vdbemem.c 8b5e1083fed2da94e315858a7edf5604a5b91804 +F src/vdbemem.c 1907e24ab431bd465f5709c30ec28a9119502f9a F src/vdbesort.c 09efa5e5098d1a159cd21f588eb118e4fe87cfde -F src/vdbetrace.c 16d39c1ef7d1f4a3a7464bea3b7b4bdd7849c415 +F src/vdbetrace.c 4f29b04edb0cec3d5fcd9b566d9f0e75c8984362 F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f F src/wal.c 10e7de7ce90865a68153f001a61f1d985cd17983 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 @@ -1198,7 +1198,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4ef4c9a7c8510203bce0941dda2f76ded8da1de2 -R b808ae1c5ded91d91c2a612e5497b640 +P d7afdcbac24350b73a30c06c45cf0f2122820e4f +R 320866568edfdafc16dd0b942dd87d16 U drh -Z 8ec5fac053656715ec4b7b6a3b299333 +Z 7641aa17b0b2d51a4b828447b0d0dc99 diff --git a/manifest.uuid b/manifest.uuid index 8fa5f719ed..55f0527798 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d7afdcbac24350b73a30c06c45cf0f2122820e4f \ No newline at end of file +4c8c89d7e62aecfe2eb735f7bb114aed6b452847 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 4bfa5f0e7e..996cf8b9b8 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -243,12 +243,13 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ i64 iValue; u8 enc = pRec->enc; if( (pRec->flags&MEM_Str)==0 ) return; + if( (pRec->flags&(MEM_Int|MEM_Real))!=0 ) return; if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ pRec->u.i = iValue; pRec->flags |= MEM_Int; }else{ - pRec->r = rValue; + pRec->u.r = rValue; pRec->flags |= MEM_Real; if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); } @@ -329,13 +330,13 @@ void sqlite3ValueApplyAffinity( /* ** pMem currently only holds a string type (or maybe a BLOB that we can ** interpret as a string if we want to). Compute its corresponding -** numeric type, if has one. Set the pMem->r and pMem->u.i fields +** numeric type, if has one. Set the pMem->u.r and pMem->u.i fields ** accordingly. */ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ assert( (pMem->flags & (MEM_Int|MEM_Real))==0 ); assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ); - if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){ + if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){ return 0; } if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ @@ -349,7 +350,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ ** none. ** ** Unlike applyNumericAffinity(), this routine does not modify pMem->flags. -** But it does set pMem->r and pMem->u.i appropriately. +** But it does set pMem->u.r and pMem->u.i appropriately. */ static u16 numericType(Mem *pMem){ if( pMem->flags & (MEM_Int|MEM_Real) ){ @@ -459,7 +460,7 @@ static void memTracePrint(Mem *p){ printf(" i:%lld", p->u.i); #ifndef SQLITE_OMIT_FLOATING_POINT }else if( p->flags & MEM_Real ){ - printf(" r:%g", p->r); + printf(" r:%g", p->u.r); #endif }else if( p->flags & MEM_RowSet ){ printf(" (rowset)"); @@ -1002,7 +1003,7 @@ case OP_Int64: { /* out2-prerelease */ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ pOut->flags = MEM_Real; assert( !sqlite3IsNaN(*pOp->p4.pReal) ); - pOut->r = *pOp->p4.pReal; + pOut->u.r = *pOp->p4.pReal; break; } #endif @@ -1479,7 +1480,7 @@ fp_math: if( sqlite3IsNaN(rB) ){ goto arithmetic_result_is_null; } - pOut->r = rB; + pOut->u.r = rB; MemSetTypeFlag(pOut, MEM_Real); if( ((type1|type2)&MEM_Real)==0 && !bIntint ){ sqlite3VdbeIntegerAffinity(pOut); @@ -3572,7 +3573,7 @@ case OP_SeekGT: { /* jump, in3 */ ** (x > 4.9) -> (x >= 5) ** (x <= 4.9) -> (x < 5) */ - if( pIn3->r<(double)iKey ){ + if( pIn3->u.r<(double)iKey ){ assert( OP_SeekGE==(OP_SeekGT-1) ); assert( OP_SeekLT==(OP_SeekLE-1) ); assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); @@ -3581,7 +3582,7 @@ case OP_SeekGT: { /* jump, in3 */ /* If the approximation iKey is smaller than the actual real search ** term, substitute <= for < and > for >=. */ - else if( pIn3->r>(double)iKey ){ + else if( pIn3->u.r>(double)iKey ){ assert( OP_SeekLE==(OP_SeekLT+1) ); assert( OP_SeekGT==(OP_SeekGE+1) ); assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 9c7378a26c..fb05e9aed2 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -161,7 +161,8 @@ struct VdbeFrame { ** integer etc.) of the same value. */ struct Mem { - union { + union MemValue { + double r; /* Real value used when MEM_Realis set in flags */ i64 i; /* Integer value used when MEM_Int is set in flags */ int nZero; /* Used when bit MEM_Zero is set in flags */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ @@ -171,10 +172,9 @@ struct Mem { u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ int n; /* Number of characters in string value, excluding '\0' */ - double r; /* Real value */ char *z; /* String or BLOB value */ - char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */ /* ShallowCopy only needs to copy the information above */ + char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */ sqlite3 *db; /* The associated database connection */ void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG diff --git a/src/vdbeapi.c b/src/vdbeapi.c index ef1167a52d..aad64aa64b 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -807,7 +807,6 @@ static const Mem *columnNullValue(void){ /* .flags = */ MEM_Null, /* .enc = */ 0, /* .n = */ 0, - /* .r = */ (double)0, /* .z = */ 0, /* .zMalloc = */ 0, /* .db = */ 0, @@ -1272,7 +1271,7 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ break; } case SQLITE_FLOAT: { - rc = sqlite3_bind_double(pStmt, i, pValue->r); + rc = sqlite3_bind_double(pStmt, i, pValue->u.r); break; } case SQLITE_BLOB: { diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 8466bfb30a..ad57f4ccd3 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1076,7 +1076,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ }else if( pMem->flags & MEM_Int ){ sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); }else if( pMem->flags & MEM_Real ){ - sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r); + sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->u.r); }else if( pMem->flags & MEM_Null ){ sqlite3_snprintf(nTemp, zTemp, "NULL"); }else{ @@ -2949,8 +2949,8 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ u64 v; u32 i; if( serial_type==7 ){ - assert( sizeof(v)==sizeof(pMem->r) ); - memcpy(&v, &pMem->r, sizeof(v)); + assert( sizeof(v)==sizeof(pMem->u.r) ); + memcpy(&v, &pMem->u.r, sizeof(v)); swapMixedEndianFloat(v); }else{ v = pMem->u.i; @@ -3020,10 +3020,10 @@ static u32 SQLITE_NOINLINE serialGet( swapMixedEndianFloat(t2); assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); #endif - assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); + assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); swapMixedEndianFloat(x); - memcpy(&pMem->r, &x, sizeof(x)); - pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; + memcpy(&pMem->u.r, &x, sizeof(x)); + pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real; } return 8; } @@ -3368,14 +3368,14 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ return 0; } if( (f1&MEM_Real)!=0 ){ - r1 = pMem1->r; + r1 = pMem1->u.r; }else if( (f1&MEM_Int)!=0 ){ r1 = (double)pMem1->u.i; }else{ return 1; } if( (f2&MEM_Real)!=0 ){ - r2 = pMem2->r; + r2 = pMem2->u.r; }else if( (f2&MEM_Int)!=0 ){ r2 = (double)pMem2->u.i; }else{ @@ -3536,9 +3536,9 @@ static int vdbeRecordCompareWithSkip( }else if( serial_type==7 ){ double rhs = (double)pRhs->u.i; sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); - if( mem1.rrhs ){ + }else if( mem1.u.r>rhs ){ rc = +1; } }else{ @@ -3560,11 +3560,11 @@ static int vdbeRecordCompareWithSkip( }else if( serial_type==0 ){ rc = -1; }else{ - double rhs = pRhs->r; + double rhs = pRhs->u.r; double lhs; sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); if( serial_type==7 ){ - lhs = mem1.r; + lhs = mem1.u.r; }else{ lhs = (double)mem1.u.i; } diff --git a/src/vdbemem.c b/src/vdbemem.c index 359abb891f..780bc5286b 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -31,6 +31,9 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){ */ assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 ); + /* Cannot be both MEM_Int and MEM_Real at the same time */ + assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); + /* If p holds a string or blob, the Mem.z must point to exactly ** one of the following: ** @@ -264,7 +267,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i); }else{ assert( fg & MEM_Real ); - sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r); + sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); } pMem->n = sqlite3Strlen30(pMem->z); pMem->enc = SQLITE_UTF8; @@ -421,7 +424,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){ if( flags & MEM_Int ){ return pMem->u.i; }else if( flags & MEM_Real ){ - return doubleToInt64(pMem->r); + return doubleToInt64(pMem->u.r); }else if( flags & (MEM_Str|MEM_Blob) ){ i64 value = 0; assert( pMem->z || pMem->n==0 ); @@ -442,7 +445,7 @@ double sqlite3VdbeRealValue(Mem *pMem){ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); if( pMem->flags & MEM_Real ){ - return pMem->r; + return pMem->u.r; }else if( pMem->flags & MEM_Int ){ return (double)pMem->u.i; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ @@ -461,12 +464,13 @@ double sqlite3VdbeRealValue(Mem *pMem){ ** MEM_Int if we can. */ void sqlite3VdbeIntegerAffinity(Mem *pMem){ + i64 ix; assert( pMem->flags & MEM_Real ); assert( (pMem->flags & MEM_RowSet)==0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - pMem->u.i = doubleToInt64(pMem->r); + ix = doubleToInt64(pMem->u.r); /* Only mark the value as an integer if ** @@ -478,11 +482,9 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){ ** the second condition under the assumption that addition overflow causes ** values to wrap around. */ - if( pMem->r==(double)pMem->u.i - && pMem->u.i>SMALLEST_INT64 - && pMem->u.iflags |= MEM_Int; + if( pMem->u.r==ix && ix>SMALLEST_INT64 && ixu.i = ix; + MemSetTypeFlag(pMem, MEM_Int); } } @@ -507,7 +509,7 @@ int sqlite3VdbeMemRealify(Mem *pMem){ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - pMem->r = sqlite3VdbeRealValue(pMem); + pMem->u.r = sqlite3VdbeRealValue(pMem); MemSetTypeFlag(pMem, MEM_Real); return SQLITE_OK; } @@ -527,7 +529,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){ if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){ MemSetTypeFlag(pMem, MEM_Int); }else{ - pMem->r = sqlite3VdbeRealValue(pMem); + pMem->u.r = sqlite3VdbeRealValue(pMem); MemSetTypeFlag(pMem, MEM_Real); sqlite3VdbeIntegerAffinity(pMem); } @@ -663,7 +665,7 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ sqlite3VdbeMemSetNull(pMem); if( !sqlite3IsNaN(val) ){ - pMem->r = val; + pMem->u.r = val; pMem->flags = MEM_Real; } } @@ -1168,14 +1170,14 @@ static int valueFromExpr( && pVal!=0 ){ sqlite3VdbeMemNumerify(pVal); - if( pVal->u.i==SMALLEST_INT64 ){ - pVal->flags &= ~MEM_Int; - pVal->flags |= MEM_Real; - pVal->r = (double)SMALLEST_INT64; + if( pVal->flags & MEM_Real ){ + pVal->u.r = -pVal->u.r; + }else if( pVal->u.i==SMALLEST_INT64 ){ + pVal->u.r = -(double)SMALLEST_INT64; + MemSetTypeFlag(pVal, MEM_Real); }else{ pVal->u.i = -pVal->u.i; } - pVal->r = -pVal->r; sqlite3ValueApplyAffinity(pVal, affinity, enc); } }else if( op==TK_NULL ){ diff --git a/src/vdbetrace.c b/src/vdbetrace.c index 362530a1d9..d27693450e 100644 --- a/src/vdbetrace.c +++ b/src/vdbetrace.c @@ -127,7 +127,7 @@ char *sqlite3VdbeExpandSql( }else if( pVar->flags & MEM_Int ){ sqlite3XPrintf(&out, 0, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ - sqlite3XPrintf(&out, 0, "%!.15g", pVar->r); + sqlite3XPrintf(&out, 0, "%!.15g", pVar->u.r); }else if( pVar->flags & MEM_Str ){ int nOut; /* Number of bytes of the string text to include in output */ #ifndef SQLITE_OMIT_UTF16