mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Make MEM_IntReal a completely independent type, meaning a floating point
value stored as an integer. This fixes a problem with arithmetic within arguments to string functions on indexes of expressions. But it is a big change and needs lots of new testcase() macros for MC/DC and so it is initially put on this branch. FossilOrigin-Name: dba836e31cb29d339b4520acb06188a892a52e45c50aba9742966b01108e251a
This commit is contained in:
35
src/vdbe.c
35
src/vdbe.c
@@ -295,7 +295,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
|
||||
double rValue;
|
||||
i64 iValue;
|
||||
u8 enc = pRec->enc;
|
||||
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str );
|
||||
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
|
||||
if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
|
||||
if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
|
||||
pRec->u.i = iValue;
|
||||
@@ -352,11 +352,11 @@ static void applyAffinity(
|
||||
** there is already a string rep, but it is pointless to waste those
|
||||
** CPU cycles. */
|
||||
if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
if( (pRec->flags&(MEM_Real|MEM_Int)) ){
|
||||
if( (pRec->flags&(MEM_Real|MEM_Int|MEM_IntReal)) ){
|
||||
sqlite3VdbeMemStringify(pRec, enc, 1);
|
||||
}
|
||||
}
|
||||
pRec->flags &= ~(MEM_Real|MEM_Int);
|
||||
pRec->flags &= ~(MEM_Real|MEM_Int|MEM_IntReal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,7 +395,7 @@ void sqlite3ValueApplyAffinity(
|
||||
** accordingly.
|
||||
*/
|
||||
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
|
||||
assert( (pMem->flags & (MEM_Int|MEM_Real))==0 );
|
||||
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
|
||||
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
|
||||
ExpandBlob(pMem);
|
||||
if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
|
||||
@@ -415,8 +415,8 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
|
||||
** But it does set pMem->u.r and pMem->u.i appropriately.
|
||||
*/
|
||||
static u16 numericType(Mem *pMem){
|
||||
if( pMem->flags & (MEM_Int|MEM_Real) ){
|
||||
return pMem->flags & (MEM_Int|MEM_Real);
|
||||
if( pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal) ){
|
||||
return pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal);
|
||||
}
|
||||
if( pMem->flags & (MEM_Str|MEM_Blob) ){
|
||||
return computeNumericType(pMem);
|
||||
@@ -514,7 +514,7 @@ static void memTracePrint(Mem *p){
|
||||
printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL");
|
||||
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
|
||||
printf(" si:%lld", p->u.i);
|
||||
}else if( (p->flags & (MEM_Int|MEM_IntReal))==(MEM_Int|MEM_IntReal) ){
|
||||
}else if( (p->flags & (MEM_IntReal))!=0 ){
|
||||
printf(" ir:%lld", p->u.i);
|
||||
}else if( p->flags & MEM_Int ){
|
||||
printf(" i:%lld", p->u.i);
|
||||
@@ -1630,7 +1630,7 @@ fp_math:
|
||||
}
|
||||
pOut->u.r = rB;
|
||||
MemSetTypeFlag(pOut, MEM_Real);
|
||||
if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
|
||||
if( ((type1|type2)&(MEM_Real|MEM_IntReal))==0 && !bIntint ){
|
||||
sqlite3VdbeIntegerAffinity(pOut);
|
||||
}
|
||||
#endif
|
||||
@@ -1801,7 +1801,7 @@ case OP_MustBeInt: { /* jump, in1 */
|
||||
*/
|
||||
case OP_RealAffinity: { /* in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
if( pIn1->flags & MEM_Int ){
|
||||
if( pIn1->flags & (MEM_Int|MEM_IntReal) ){
|
||||
sqlite3VdbeMemRealify(pIn1);
|
||||
}
|
||||
break;
|
||||
@@ -1993,7 +1993,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
affinity = pOp->p5 & SQLITE_AFF_MASK;
|
||||
if( affinity>=SQLITE_AFF_NUMERIC ){
|
||||
if( (flags1 | flags3)&MEM_Str ){
|
||||
if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
|
||||
if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
|
||||
applyNumericAffinity(pIn1,0);
|
||||
assert( flags3==pIn3->flags );
|
||||
/* testcase( flags3!=pIn3->flags );
|
||||
@@ -2003,7 +2003,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
** in case our analysis is incorrect, so it is left in. */
|
||||
flags3 = pIn3->flags;
|
||||
}
|
||||
if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
|
||||
if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
|
||||
applyNumericAffinity(pIn3,0);
|
||||
}
|
||||
}
|
||||
@@ -2016,17 +2016,19 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
goto compare_op;
|
||||
}
|
||||
}else if( affinity==SQLITE_AFF_TEXT ){
|
||||
if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
|
||||
if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
|
||||
testcase( pIn1->flags & MEM_Int );
|
||||
testcase( pIn1->flags & MEM_Real );
|
||||
testcase( pIn1->flags & MEM_IntReal );
|
||||
sqlite3VdbeMemStringify(pIn1, encoding, 1);
|
||||
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
|
||||
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
|
||||
assert( pIn1!=pIn3 );
|
||||
}
|
||||
if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){
|
||||
if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
|
||||
testcase( pIn3->flags & MEM_Int );
|
||||
testcase( pIn3->flags & MEM_Real );
|
||||
testcase( pIn3->flags & MEM_IntReal );
|
||||
sqlite3VdbeMemStringify(pIn3, encoding, 1);
|
||||
testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
|
||||
flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
|
||||
@@ -2790,6 +2792,7 @@ case OP_Affinity: {
|
||||
/* When applying REAL affinity, if the result is still MEM_Int,
|
||||
** indicate that REAL is actually desired */
|
||||
pIn1->flags |= MEM_IntReal;
|
||||
pIn1->flags &= ~MEM_Int;
|
||||
}
|
||||
REGISTER_TRACE((int)(pIn1-aMem), pIn1);
|
||||
zAffinity++;
|
||||
@@ -3987,14 +3990,14 @@ case OP_SeekGT: { /* jump, in3, group */
|
||||
** blob, or NULL. But it needs to be an integer before we can do
|
||||
** the seek, so convert it. */
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
|
||||
if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){
|
||||
applyNumericAffinity(pIn3, 0);
|
||||
}
|
||||
iKey = sqlite3VdbeIntValue(pIn3);
|
||||
|
||||
/* If the P3 value could not be converted into an integer without
|
||||
** loss of information, then special processing is required... */
|
||||
if( (pIn3->flags & MEM_Int)==0 ){
|
||||
if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
|
||||
if( (pIn3->flags & MEM_Real)==0 ){
|
||||
/* If the P3 value cannot be converted into any kind of a number,
|
||||
** then the seek is not possible, so jump to P2 */
|
||||
@@ -4379,7 +4382,7 @@ case OP_SeekRowid: { /* jump, in3 */
|
||||
u64 iKey;
|
||||
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
if( (pIn3->flags & MEM_Int)==0 ){
|
||||
if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
|
||||
/* Make sure pIn3->u.i contains a valid integer representation of
|
||||
** the key value, but do not change the datatype of the register, as
|
||||
** other parts of the perpared statement might be depending on the
|
||||
|
Reference in New Issue
Block a user