Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Use decimal arithmetic in affinity routines. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sqlite4-num |
Files: | files | file ages | folders |
SHA1: |
ae34cd8492cf98b71640cedca034b401 |
User & Date: | dan 2013-05-31 17:13:32.128 |
Context
2013-05-31
| ||
19:19 | Remove uses of type 'double' from the vdbe. check-in: e018823162 user: dan tags: sqlite4-num | |
17:13 | Use decimal arithmetic in affinity routines. check-in: ae34cd8492 user: dan tags: sqlite4-num | |
2013-05-30
| ||
19:01 | Use the same code to encode keys for rowid indexes as regular indexes. check-in: 9265ac66c8 user: dan tags: sqlite4-num | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
1902 1903 1904 1905 1906 1907 1908 | ** like the continuation of the number. */ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ if( ALWAYS(z!=0) ){ int s = sizeof(sqlite4_num); sqlite4_num *p = (sqlite4_num *)sqlite4DbMallocZero(sqlite4VdbeDb(v), s); if( p ){ | | | 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 | ** like the continuation of the number. */ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ if( ALWAYS(z!=0) ){ int s = sizeof(sqlite4_num); sqlite4_num *p = (sqlite4_num *)sqlite4DbMallocZero(sqlite4VdbeDb(v), s); if( p ){ *p = sqlite4_num_from_text(z, -1, 0, 0); assert( p->sign==0 ); assert( negateFlag==0 || negateFlag==1 ); p->sign = negateFlag; sqlite4VdbeAddOp4(v, OP_Num, 0, iMem, 0, (const char *)p, P4_NUM); } #if 0 double value; |
︙ | ︙ | |||
1944 1945 1946 1947 1948 1949 1950 | int c; i64 value; const char *z = pExpr->u.zToken; assert( z!=0 ); p = (sqlite4_num *)sqlite4DbMallocRaw(pParse->db, sizeof(sqlite4_num)); if( p ){ | | | 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 | int c; i64 value; const char *z = pExpr->u.zToken; assert( z!=0 ); p = (sqlite4_num *)sqlite4DbMallocRaw(pParse->db, sizeof(sqlite4_num)); if( p ){ *p = sqlite4_num_from_text(z, -1, (negFlag ? SQLITE4_NEGATIVE : 0), 0); sqlite4VdbeAddOp4(v, OP_Num, p->e==0, iMem, 0, (const char *)p, P4_NUM); } #if 0 c = sqlite4Atoi64(z, &value, sqlite4Strlen30(z), SQLITE4_UTF8); if( c==0 || (c==2 && negFlag) ){ char *zV; |
︙ | ︙ |
Changes to src/math.c.
︙ | ︙ | |||
307 308 309 310 311 312 313 | ** are scanned, which we assume is more than will be found in any valid ** numeric string. ** ** If the value does not contain a decimal point or exponent, and is ** within the range of a signed 64-bit integer, it is guaranteed that ** the exponent of the returned value is zero. */ | | > > > > > > > < > < > | > < > | | | | > | | | | > | | | > | < > > > > | > > | > | | | < | < < < < < | < < < < < | | < < | > | | | | | < | > > > > | > > > > | | | | > > > | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 | ** are scanned, which we assume is more than will be found in any valid ** numeric string. ** ** If the value does not contain a decimal point or exponent, and is ** within the range of a signed 64-bit integer, it is guaranteed that ** the exponent of the returned value is zero. */ sqlite4_num sqlite4_num_from_text( const char *zIn, /* Pointer to text to parse */ int nIn, /* Size of zIn in bytes or (-ve) */ unsigned flags, /* Conversion flags */ int *pbReal /* OUT: True if text looks like a real */ ){ /* Return this value (NaN) if a parse error occurs. */ static const sqlite4_num error_value = {0, 0, SQLITE4_MX_EXP+1, 0}; static const i64 L10 = (LARGEST_INT64 / 10); int aMaxFinal[2] = {7, 8}; static int one = 1; /* Used to test machine endianness */ int bRnd = 1; /* If mantissa overflows, round it */ int bReal = 0; /* If text looks like a real */ int seenRadix = 0; /* True after decimal point has been parsed */ int seenDigit = 0; /* True after first non-zero digit parsed */ int incr = 1; /* 1 for utf-8, 2 for utf-16 */ sqlite4_num r; /* Value to return */ char c; int nDigit = 0; int i; assert( L10==922337203685477580 ); memset(&r, 0, sizeof(r)); if( nIn<0 ) nIn = 1000000000; c = flags & 0xf; if( c==0 || c==SQLITE4_UTF8 ){ incr = 1; }else{ if( c==SQLITE4_UTF16 ){ c = (3 - *(char*)&one); } assert( c==SQLITE4_UTF16LE || c==SQLITE4_UTF16BE ); incr = 2; if( c==SQLITE4_UTF16BE ){ zIn += 1; nIn -= 1; } } /* If the IGNORE_WHITESPACE flag is set, ignore any leading whitespace. */ i = 0; if( flags & SQLITE4_IGNORE_WHITESPACE ){ while( sqlite4Isspace(zIn[i]) && i<nIn ) i+=incr; } if( nIn<=i ) return error_value; /* Check for a leading '+' or '-' symbol. */ if( zIn[i]=='-' ){ r.sign = 1; i += incr; }else if( zIn[i]=='+' ){ i += incr; }else if( flags & SQLITE4_NEGATIVE ){ r.sign = 1; } if( nIn<=i ) return error_value; /* Check for the string "inf". This is a special case. */ if( (flags & SQLITE4_INTEGER_ONLY)==0 && (nIn-i)>=incr*3 && ((c=zIn[i])=='i' || c=='I') && ((c=zIn[i+incr])=='n' || c=='N') && ((c=zIn[i+incr*2])=='f' || c=='F') ){ r.e = SQLITE4_MX_EXP+1; r.m = 1; if( pbReal ) *pbReal = 1; goto finished; } for( ; i<nIn && (c = zIn[i])!=0; i+=incr){ if( c>='0' && c<='9' ){ int iDigit = (c - '0'); if( iDigit==0 && seenDigit==0 ){ /* Handle leading zeroes. If they occur to the right of the decimal ** point they can just be ignored. Otherwise, decrease the exponent ** by one. */ if( seenRadix ) r.e--; continue; } seenDigit = 1; if( r.e>0 || r.m>L10 || (r.m==L10 && iDigit>aMaxFinal[r.sign]) ){ /* Mantissa overflow. */ if( seenRadix==0 ) r.e++; if( iDigit!=0 ){ r.approx = 1; } if( bRnd ){ if( iDigit>5 && r.m<((u64)LARGEST_INT64 + r.sign)) r.m++; bRnd = 0; } bReal = 1; }else{ if( seenRadix ) r.e -= 1; r.m = (r.m*10) + iDigit; } }else{ if( flags & SQLITE4_INTEGER_ONLY ) goto finished; if( c=='.' ){ /* Permit only a single radix in each number */ if( seenRadix ) goto finished; seenRadix = 1; bReal = 1; }else if( c=='e' || c=='E' ){ int f = (flags & (SQLITE4_PREFIX_ONLY|SQLITE4_IGNORE_WHITESPACE)); sqlite4_num exp; exp = sqlite4_num_from_text(&zIn[i+incr], nIn-i-incr, f, 0); if( sqlite4_num_isnan(exp) ) goto finished; if( exp.e || exp.m>999 ) goto finished; bReal = 1; r.e += (int)(exp.m) * (exp.sign ? -1 : 1); i = nIn; break; }else{ goto finished; } } } finished: /* Check for a parse error. If one has occurred, set the return value ** to NaN. */ if( (flags & SQLITE4_PREFIX_ONLY)==0 && i<nIn && zIn[i] ){ if( flags & SQLITE4_IGNORE_WHITESPACE ){ while( i<nIn && sqlite4Isspace(zIn[i]) ) i += incr; } if( i<nIn && zIn[i] ){ r.e = SQLITE4_MX_EXP+1; r.m = 0; } } if( pbReal ) *pbReal = bReal; return r; } /* ** Convert an sqlite4_int64 to a number and return that number. */ sqlite4_num sqlite4_num_from_int64(sqlite4_int64 n){ |
︙ | ︙ | |||
524 525 526 527 528 529 530 | iRet = iRet / 10; } *piOut = iRet; return SQLITE4_OK; } | < < < < < < < < < < < < < | 539 540 541 542 543 544 545 546 547 548 549 550 551 552 | iRet = iRet / 10; } *piOut = iRet; return SQLITE4_OK; } /* ** Convert an integer into text in the buffer supplied. The ** text is zero-terminated and right-justified in the buffer. ** A pointer to the first character of text is returned. ** ** The buffer needs to be at least 21 bytes in length. */ |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
4108 4109 4110 4111 4112 4113 4114 | sqlite4_num sqlite4_num_sub(sqlite4_num, sqlite4_num); sqlite4_num sqlite4_num_mul(sqlite4_num, sqlite4_num); sqlite4_num sqlite4_num_div(sqlite4_num, sqlite4_num); int sqlite4_num_isinf(sqlite4_num); int sqlite4_num_isnan(sqlite4_num); sqlite4_num sqlite4_num_round(sqlite4_num, int iDigit); int sqlite4_num_compare(sqlite4_num, sqlite4_num); | | > | 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 | sqlite4_num sqlite4_num_sub(sqlite4_num, sqlite4_num); sqlite4_num sqlite4_num_mul(sqlite4_num, sqlite4_num); sqlite4_num sqlite4_num_div(sqlite4_num, sqlite4_num); int sqlite4_num_isinf(sqlite4_num); int sqlite4_num_isnan(sqlite4_num); sqlite4_num sqlite4_num_round(sqlite4_num, int iDigit); int sqlite4_num_compare(sqlite4_num, sqlite4_num); sqlite4_num sqlite4_num_from_text(const char*, int n, unsigned flags, int*); sqlite4_num sqlite4_num_from_int64(sqlite4_int64); sqlite4_num sqlite4_num_from_double(double); int sqlite4_num_to_int32(sqlite4_num, int*); int sqlite4_num_to_int64(sqlite4_num, sqlite4_int64*); int sqlite4_num_to_double(sqlite4_num, double *); int sqlite4_num_to_text(sqlite4_num, char*, int); /* ** CAPI4REF: Flags For Text-To-Numeric Conversion */ #define SQLITE4_PREFIX_ONLY 0x10 #define SQLITE4_IGNORE_WHITESPACE 0x20 #define SQLITE4_NEGATIVE 0x40 #define SQLITE4_INTEGER_ONLY 0x80 typedef struct sqlite4_tokenizer sqlite4_tokenizer; /* ** CAPI4REF: Register an FTS tokenizer implementation ** ** xTokenize: |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
225 226 227 228 229 230 231 | /* ** Try to convert a value into a numeric representation if we can ** do so without loss of information. In other words, if the string ** looks like a number, convert it into a number. If it does not ** look like a number, leave it alone. */ static void applyNumericAffinity(Mem *pRec){ | | < < | < > | | | < < > | | | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | /* ** Try to convert a value into a numeric representation if we can ** do so without loss of information. In other words, if the string ** looks like a number, convert it into a number. If it does not ** look like a number, leave it alone. */ static void applyNumericAffinity(Mem *pRec){ if( (pRec->flags & (MEM_Real|MEM_Int))==0 && (pRec->flags & MEM_Str) ){ int flags = pRec->enc | SQLITE4_IGNORE_WHITESPACE; int bReal = 0; sqlite4_num num; num = sqlite4_num_from_text(pRec->z, pRec->n, flags, &bReal); if( sqlite4_num_isnan(num)==0 ){ pRec->u.num = num; MemSetTypeFlag(pRec, (bReal ? MEM_Real : MEM_Int)); } } } /* ** Processing is determine by the affinity parameter: ** |
︙ | ︙ | |||
417 418 419 420 421 422 423 | fprintf(out, "REG[%d] = ", iReg); memTracePrint(out, p); fprintf(out, "\n"); } #endif #ifdef SQLITE4_DEBUG | > > > > > > > > | > | | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | fprintf(out, "REG[%d] = ", iReg); memTracePrint(out, p); fprintf(out, "\n"); } #endif #ifdef SQLITE4_DEBUG static int assertFlagsOk(Mem *p){ u16 flags = p->flags; assert( (flags&MEM_Int)==0 || (flags&MEM_Real)==0 ); return 1; } #endif #ifdef SQLITE4_DEBUG # define REGISTER_TRACE(R,M) \ if(assertFlagsOk(M) && p->trace)registerTrace(p->trace,R,M) #else # define REGISTER_TRACE(R,M) #endif #ifdef VDBE_PROFILE /* ** hwtime.h contains inline assembler code for implementing |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
349 350 351 352 353 354 355 | ** Extract and return a numeric value from memory cell pMem. This call ** does not modify the contents or flags of *pMem in any way. */ sqlite4_num sqlite4VdbeNumValue(Mem *pMem){ if( pMem->flags & (MEM_Real|MEM_Int) ){ return pMem->u.num; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ | > | | 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | ** Extract and return a numeric value from memory cell pMem. This call ** does not modify the contents or flags of *pMem in any way. */ sqlite4_num sqlite4VdbeNumValue(Mem *pMem){ if( pMem->flags & (MEM_Real|MEM_Int) ){ return pMem->u.num; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ int flags = SQLITE4_PREFIX_ONLY | pMem->enc; return sqlite4_num_from_text(pMem->z, pMem->n, flags, 0); }else{ sqlite4_num zero = {0,0,0,0}; return zero; } } /* |
︙ | ︙ | |||
425 426 427 428 429 430 431 | ** ** Every effort is made to force the conversion, even if the input ** is a string that does not look completely like a number. Convert ** as much of the string as we can and ignore the rest. */ int sqlite4VdbeMemNumerify(Mem *pMem){ if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){ | > | | < | < < < | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | ** ** Every effort is made to force the conversion, even if the input ** is a string that does not look completely like a number. Convert ** as much of the string as we can and ignore the rest. */ int sqlite4VdbeMemNumerify(Mem *pMem){ if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){ int bReal = 0; int flags = (pMem->enc | SQLITE4_PREFIX_ONLY | SQLITE4_IGNORE_WHITESPACE); assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) ); pMem->u.num = sqlite4_num_from_text(pMem->z, pMem->n, flags, &bReal); MemSetTypeFlag(pMem, (bReal ? MEM_Real : MEM_Int)); } assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); pMem->flags &= ~(MEM_Str|MEM_Blob); return SQLITE4_OK; } /* |
︙ | ︙ |