Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Further progress on decimal arithmetic. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sqlite4-num |
Files: | files | file ages | folders |
SHA1: |
b55b217f6a98b255415e5e493fbace35 |
User & Date: | dan 2013-05-28 20:33:15.057 |
Context
2013-05-29
| ||
18:52 | Further progress on this. src4.test is now passing again. check-in: 9cf2ab46f5 user: dan tags: sqlite4-num | |
2013-05-28
| ||
20:33 | Further progress on decimal arithmetic. check-in: b55b217f6a user: dan tags: sqlite4-num | |
2013-05-25
| ||
20:13 | Further progress on using decimal arithmetic. check-in: f875ba1944 user: dan tags: sqlite4-num | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
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)); 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.
︙ | ︙ | |||
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | ** is 0. If that assumption is violated, then this routine can ** yield an anomolous result. ** ** Conversion stops at the first \000 character. At most nIn bytes ** of zIn are examined. Or if nIn is negative, up to a billion bytes ** are scanned, which we assume is more than will be found in any valid ** numeric string. */ sqlite4_num sqlite4_num_from_text(const char *zIn, int nIn, unsigned flags){ static int one = 1; /* Used to test machine endianness */ int seenRadix = 0; /* True after decimal point has been parsed */ int incr = 1; /* 1 for utf-8, 2 for utf-16 */ int bInvalid = 1; /* True for a bad parse */ sqlite4_num r; /* Value to return */ char c; int nDigit = 0; int i; 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 ){ | > > > > > > > > > > > > | 302 303 304 305 306 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 | ** is 0. If that assumption is violated, then this routine can ** yield an anomolous result. ** ** Conversion stops at the first \000 character. At most nIn bytes ** of zIn are examined. Or if nIn is negative, up to a billion bytes ** 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, int nIn, unsigned flags){ 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 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 */ int bInvalid = 1; /* True for a bad parse */ 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 ){ |
︙ | ︙ | |||
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | /* Check for a leading '+' or '-' symbol. */ if( zIn[i]=='-' ){ r.sign = 1; i += incr; }else if( zIn[i]=='+' ){ i += incr; } if( nIn<=i ) goto finished; /* Check for the string "inf". This is a special case. */ if( (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 = nIn<=i+incr*3 || zIn[i+incr*3]==0; return r; } while( i<nIn && (c = zIn[i])!=0 ){ i += incr; if( c>='0' && c<='9' ){ | > > > > | > > > | | | < > > | > > > > > < | > > | 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 | /* 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 ) goto finished; /* Check for the string "inf". This is a special case. */ if( (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 = nIn<=i+incr*3 || zIn[i+incr*3]==0; return r; } while( 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; } }else{ if( seenRadix ) r.e -= 1; r.m = (r.m*10) + iDigit; } }else if( c=='.' ){ seenRadix = 1; }else if( c=='e' || c=='E' ){ int exp = 0; int expsign = 0; int nEDigit = 0; if( zIn[i]=='-' ){ |
︙ | ︙ | |||
403 404 405 406 407 408 409 | finished: if( bInvalid && (flags & SQLITE4_PREFIX_ONLY)==0 ){ r.e = SQLITE4_MX_EXP+1; r.m = 0; } | < < < < < | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 | finished: if( bInvalid && (flags & SQLITE4_PREFIX_ONLY)==0 ){ r.e = SQLITE4_MX_EXP+1; r.m = 0; } return r; } /* ** Convert an sqlite4_int64 to a number and return that number. */ sqlite4_num sqlite4_num_from_int64(sqlite4_int64 n){ |
︙ | ︙ | |||
548 549 550 551 552 553 554 | } /* ** Convert a number into text. Store the result in zOut[]. The ** zOut buffer must be at laest 30 characters in length. The output ** will be zero-terminated. */ | | | 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | } /* ** Convert a number into text. Store the result in zOut[]. The ** zOut buffer must be at laest 30 characters in length. The output ** will be zero-terminated. */ int sqlite4_num_to_text(sqlite4_num x, char *zOut, int bReal){ char zBuf[24]; int nOut = 0; char *zNum; int n; static const char zeros[] = "0000000000000000000000000"; if( x.sign && x.m>0 ){ |
︙ | ︙ | |||
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 | memcpy(zOut, zNum, n+1); nOut += n; if( x.e>0 ){ memcpy(&zOut[nOut], zeros, x.e); zOut[nOut+x.e] = 0; nOut += x.e; } return nOut; } if( x.e<0 && n+x.e > 0 ){ /* Fractional values where the decimal point occurs within the ** significant digits. ex: 12.345 */ int m = n+x.e; memcpy(zOut, zNum, m); nOut += m; zOut += m; zNum += m; n -= m; removeTrailingZeros(zNum, &n); if( n>0 ){ zOut[0] = '.'; memcpy(zOut+1, zNum, n); nOut += n; zOut[n+1] = 0; }else{ | > > > > > > > > | > | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 | memcpy(zOut, zNum, n+1); nOut += n; if( x.e>0 ){ memcpy(&zOut[nOut], zeros, x.e); zOut[nOut+x.e] = 0; nOut += x.e; } if( bReal ){ memcpy(&zOut[nOut], ".0", 3); nOut += 2; } return nOut; } if( x.e<0 && n+x.e > 0 ){ /* Fractional values where the decimal point occurs within the ** significant digits. ex: 12.345 */ int m = n+x.e; memcpy(zOut, zNum, m); nOut += m; zOut += m; zNum += m; n -= m; removeTrailingZeros(zNum, &n); if( n>0 ){ zOut[0] = '.'; memcpy(zOut+1, zNum, n); nOut += n; zOut[n+1] = 0; }else{ if( bReal ){ memcpy(zOut, ".0", 3); nOut += 2; }else{ zOut[0] = 0; } } return nOut; } if( x.e<0 && x.e >= -n-5 ){ /* Values less than 1 and with no more than 5 subsequent zeros prior ** to the first significant digit. Ex: 0.0000012345 */ int j = -(n + x.e); |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
4114 4115 4116 4117 4118 4119 4120 | int sqlite4_num_compare(sqlite4_num, sqlite4_num); sqlite4_num sqlite4_num_from_text(const char*, int n, unsigned flags); 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 *); | | > | 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 | int sqlite4_num_compare(sqlite4_num, sqlite4_num); sqlite4_num sqlite4_num_from_text(const char*, int n, unsigned flags); 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 typedef struct sqlite4_tokenizer sqlite4_tokenizer; /* ** CAPI4REF: Register an FTS tokenizer implementation ** ** xTokenize: |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
393 394 395 396 397 398 399 | */ static void memTracePrint(FILE *out, Mem *p){ if( p->flags & MEM_Null ){ fprintf(out, " NULL"); }else if( p->flags & (MEM_Int|MEM_Real) ){ char aNum[31]; char *zFlags = "r"; | | | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | */ static void memTracePrint(FILE *out, Mem *p){ if( p->flags & MEM_Null ){ fprintf(out, " NULL"); }else if( p->flags & (MEM_Int|MEM_Real) ){ char aNum[31]; char *zFlags = "r"; sqlite4_num_to_text(p->u.num, aNum, (p->flags & MEM_Real)); if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ zFlags = "si"; }else if( p->flags & MEM_Int ){ zFlags = "i"; } fprintf(out, " %s:%s", zFlags, aNum); }else if( p->flags & MEM_RowSet ){ |
︙ | ︙ | |||
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 | case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ int flags; /* Combined MEM_* flags from both inputs */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ #if 0 double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ #endif pIn1 = &aMem[pOp->p1]; applyNumericAffinity(pIn1); pIn2 = &aMem[pOp->p2]; applyNumericAffinity(pIn2); pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | < | < | > > | 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 | case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ int flags; /* Combined MEM_* flags from both inputs */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ i64 iOut; #if 0 double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ #endif pIn1 = &aMem[pOp->p1]; applyNumericAffinity(pIn1); pIn2 = &aMem[pOp->p2]; applyNumericAffinity(pIn2); pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (pIn1->flags&MEM_Int) && (pIn2->flags&MEM_Int) ){ sqlite4_num_to_int64(pIn1->u.num, &iA); sqlite4_num_to_int64(pIn2->u.num, &iB); switch( pOp->opcode ){ case OP_Add: if( sqlite4AddInt64(&iB,iA) ) goto fp_math; break; case OP_Subtract: if( sqlite4SubInt64(&iB,iA) ) goto fp_math; break; case OP_Multiply: if( sqlite4MulInt64(&iB,iA) ) goto fp_math; break; case OP_Divide: { if( iA==0 ) goto arithmetic_result_is_null; if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math; iB /= iA; break; } default: { if( iA==0 ) goto arithmetic_result_is_null; if( iA==-1 ) iA = 1; iB %= iA; break; } } pOut->u.num = sqlite4_num_from_int64(iB); MemSetTypeFlag(pOut, MEM_Int); break; }else{ fp_math: switch( pOp->opcode ){ case OP_Add: pOut->u.num = sqlite4_num_add(pIn1->u.num, pIn2->u.num); break; case OP_Subtract: pOut->u.num = sqlite4_num_sub(pIn2->u.num, pIn1->u.num); break; case OP_Multiply: pOut->u.num = sqlite4_num_mul(pIn1->u.num, pIn2->u.num); break; case OP_Divide: pOut->u.num = sqlite4_num_div(pIn2->u.num, pIn1->u.num); break; default: { sqlite4_num_to_int64(pIn1->u.num, &iA); sqlite4_num_to_int64(pIn2->u.num, &iB); if( iA==0 ) goto arithmetic_result_is_null; pOut->u.num = sqlite4_num_from_int64(iB % iA); break; } } if( sqlite4_num_isnan(pOut->u.num) ){ goto arithmetic_result_is_null; }else{ MemSetTypeFlag(pOut, MEM_Real); } } break; #if 0 if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ iA = pIn1->u.i; iB = pIn2->u.i; switch( pOp->opcode ){ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
899 900 901 902 903 904 905 | } case P4_MEM: { Mem *pMem = pOp->p4.pMem; if( pMem->flags & MEM_Str ){ zP4 = pMem->z; }else if( pMem->flags & (MEM_Int|MEM_Real) ){ char aOut[30]; | | | 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 | } case P4_MEM: { Mem *pMem = pOp->p4.pMem; if( pMem->flags & MEM_Str ){ zP4 = pMem->z; }else if( pMem->flags & (MEM_Int|MEM_Real) ){ char aOut[30]; sqlite4_num_to_text(pMem->u.num, aOut, (pMem->flags & MEM_Real)); sqlite4_snprintf(zTemp, nTemp, "%s", aOut); }else if( pMem->flags & MEM_Null ){ sqlite4_snprintf(zTemp, nTemp, "NULL"); }else{ assert( pMem->flags & MEM_Blob ); zP4 = "(blob)"; } |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
172 173 174 175 176 177 178 | assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) ); assert( !(fg&(MEM_Str|MEM_Blob)) ); assert( fg&(MEM_Int|MEM_Real) ); assert( (pMem->flags&MEM_RowSet)==0 ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); | < | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) ); assert( !(fg&(MEM_Str|MEM_Blob)) ); assert( fg&(MEM_Int|MEM_Real) ); assert( (pMem->flags&MEM_RowSet)==0 ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); if( sqlite4VdbeMemGrow(pMem, nByte, 0) ){ return SQLITE4_NOMEM; } /* For a Real or Integer, use sqlite4_mprintf() to produce the UTF-8 ** string representation of the value. Then, if the required encoding ** is UTF-16le or UTF-16be do a translation. ** ** FIX ME: It would be better if sqlite4_snprintf() could do UTF-16. */ sqlite4_num_to_text(pMem->u.num, pMem->z, (pMem->flags & MEM_Int)==0); pMem->n = sqlite4Strlen30(pMem->z); pMem->enc = SQLITE4_UTF8; pMem->flags |= MEM_Str|MEM_Term; sqlite4VdbeChangeEncoding(pMem, enc); return rc; } |
︙ | ︙ |
Changes to src/vdbetrace.c.
︙ | ︙ | |||
117 118 119 120 121 122 123 | nextIndex = idx + 1; assert( idx>0 && idx<=p->nVar ); pVar = &p->aVar[idx-1]; if( pVar->flags & MEM_Null ){ sqlite4StrAccumAppend(&out, "NULL", 4); }else if( pVar->flags & (MEM_Int|MEM_Real) ){ char aOut[30]; | | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | nextIndex = idx + 1; assert( idx>0 && idx<=p->nVar ); pVar = &p->aVar[idx-1]; if( pVar->flags & MEM_Null ){ sqlite4StrAccumAppend(&out, "NULL", 4); }else if( pVar->flags & (MEM_Int|MEM_Real) ){ char aOut[30]; sqlite4_num_to_text(pVar->u.num, aOut, (pVar->flags & MEM_Real)); sqlite4XPrintf(&out, "%s", aOut); }else if( pVar->flags & MEM_Str ){ #ifndef SQLITE4_OMIT_UTF16 u8 enc = ENC(db); if( enc!=SQLITE4_UTF8 ){ Mem utf8; memset(&utf8, 0, sizeof(utf8)); |
︙ | ︙ |
Changes to test/num.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # This file implements regression tests for SQLite library. The # focus of this file is testing the sqlite_*_printf() interface. # # $Id: printf.test,v 1.31 2009/02/01 00:21:10 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test num-1.1.1 { sqlite4_num_compare 20 20 } {equal} do_test num-1.1.2 { sqlite4_num_compare 20 2e1 } {equal} | > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # This file implements regression tests for SQLite library. The # focus of this file is testing the sqlite_*_printf() interface. # # $Id: printf.test,v 1.31 2009/02/01 00:21:10 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl if 0 { do_test num-1.1.1 { sqlite4_num_compare 20 20 } {equal} do_test num-1.1.2 { sqlite4_num_compare 20 2e1 } {equal} |
︙ | ︙ | |||
88 89 90 91 92 93 94 | do_test num-6.1.4 { sqlite4_num_to_text [sqlite4_num_div 22 10] } {2.2} #------------------------------------------------------------------------- # The following test cases - num-7.* - test the sqlite4_num_from_double() # API function. | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | do_test num-6.1.4 { sqlite4_num_to_text [sqlite4_num_div 22 10] } {2.2} #------------------------------------------------------------------------- # The following test cases - num-7.* - test the sqlite4_num_from_double() # API function. # foreach {tn in out} { 1 1.0 {sign:0 e:0 m:1} 2 -1.0 {sign:1 e:0 m:1} 3 1.5 {sign:0 e:-1 m:15} 4 -1.5 {sign:1 e:-1 m:15} 5 0.15 {sign:0 e:-2 m:15} 6 -0.15 {sign:1 e:-2 m:15} 7 45.345687 {sign:0 e:-6 m:45345687} 8 1000000000000000000 {sign:0 e:18 m:1} } { do_test num-7.1.$tn { set res [sqlite4_num_from_double $in] list [lindex $res 0] [lindex $res 2] [lindex $res 3] } [list [lindex $out 0] [lindex $out 1] [lindex $out 2]] } } #------------------------------------------------------------------------- # Test the boundary conditions in sqlite4_num_from_text() for parsing # values that can fit in a signed 64-bit integer variable. And others. # foreach {tn in out} { 0 9223372036854775806 {sign:0 approx:0 e:0 m:9223372036854775806} 1 9223372036854775807 {sign:0 approx:0 e:0 m:9223372036854775807} 2 -9223372036854775808 {sign:1 approx:0 e:0 m:9223372036854775808} 3 -9223372036854775807 {sign:1 approx:0 e:0 m:9223372036854775807} 4 -9223372036854775806 {sign:1 approx:0 e:0 m:9223372036854775806} } { do_test num-8.1.$tn { sqlite4_num_from_text $in } $out } foreach {tn in out} { 0 9223372036854775808 {sign:0 approx:1 e:1 m:922337203685477581} 1 9223372036854775809 {sign:0 approx:1 e:1 m:922337203685477581} 2 9223372036854775810 {sign:0 approx:0 e:1 m:922337203685477581} 3 9223372036854775811 {sign:0 approx:1 e:1 m:922337203685477581} 4 -9223372036854775809 {sign:1 approx:1 e:1 m:922337203685477581} 5 -9223372036854775810 {sign:1 approx:0 e:1 m:922337203685477581} 6 -9223372036854775811 {sign:1 approx:1 e:1 m:922337203685477581} } { do_test num-8.2.$tn { sqlite4_num_from_text $in } $out } foreach {tn in out} { 0 2147483648 {sign:0 approx:0 e:0 m:2147483648} 1 -2147483648 {sign:1 approx:0 e:0 m:2147483648} } { do_test num-8.3.$tn { sqlite4_num_from_text $in } $out } #------------------------------------------------------------------------- # Test parsing of values with decimal points. # foreach {tn in out} { 0 1.5 {sign:0 approx:0 e:-1 m:15} 1 1.005 {sign:0 approx:0 e:-3 m:1005} 2 00000 {sign:0 approx:0 e:0 m:0} 3 00.000 {sign:0 approx:0 e:-3 m:0} 4 -1.005 {sign:1 approx:0 e:-3 m:1005} 5.1 1 {sign:0 approx:0 e:0 m:1} 5.2 1.0 {sign:0 approx:0 e:-1 m:10} 5.3 1. {sign:0 approx:0 e:0 m:1} 5.4 1e0 {sign:0 approx:0 e:0 m:1} } { do_test num-9.1.$tn { sqlite4_num_from_text $in } [list {*}$out] } #------------------------------------------------------------------------- finish_test |
Added test/num2.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # 2013 May 29 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix num2 do_execsql_test 1.1 { SELECT 1.0 } {1.0} do_execsql_test 1.2 { SELECT typeof(1.0) } {real} do_execsql_test 1.3 { SELECT cast(1.0 AS TEXT) } {1.0} do_execsql_test 1.4 { SELECT cast((1.0+1.0) AS TEXT) } {2.0} do_execsql_test 1.5 { SELECT typeof(1.0+1.0) } {real} do_execsql_test 1.6 { SELECT typeof(1.0*1.0) } {real} do_execsql_test 1.7 { SELECT typeof(1.0/1.0) } {real} do_execsql_test 1.8 { SELECT typeof(1.0-1.0) } {real} do_execsql_test 1.8 { SELECT typeof(1.0%1.0) } {real} finish_test |
Changes to test/permutations.test.
︙ | ︙ | |||
181 182 183 184 185 186 187 | misc5.test misc6.test misuse.test notnull.test null.test printf.test quote.test | | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | misc5.test misc6.test misuse.test notnull.test null.test printf.test quote.test savepoint.test savepoint5.test select1.test select2.test select3.test select4.test select5.test select6.test select7.test select8.test select9.test selectA.test selectB.test selectC.test sort.test storage1.test |
︙ | ︙ |
Changes to test/savepoint2.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 | } } {1024} wal_check_journal_mode savepoint2-1.1 unset -nocomplain ::sig unset -nocomplain SQL | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | } } {1024} wal_check_journal_mode savepoint2-1.1 unset -nocomplain ::sig unset -nocomplain SQL set iterations 2 set SQL(1) { DELETE FROM t3 WHERE random()%10!=0; INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; } set SQL(2) { |
︙ | ︙ | |||
146 147 148 149 150 151 152 | # Check that the connection is still running in WAL mode. wal_check_journal_mode savepoint2-$ii.7 } unset -nocomplain ::sig unset -nocomplain SQL | < < | 146 147 148 149 150 151 152 | # Check that the connection is still running in WAL mode. wal_check_journal_mode savepoint2-$ii.7 } unset -nocomplain ::sig unset -nocomplain SQL |
Changes to test/select1.test.
︙ | ︙ | |||
292 293 294 295 296 297 298 | # ORDER BY expressions # do_test select1-4.1 { set v [catch {execsql {SELECT f1 FROM test1 ORDER BY f1}} msg] lappend v $msg } {0 {11 33}} do_test select1-4.2 { | < < | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | # ORDER BY expressions # do_test select1-4.1 { set v [catch {execsql {SELECT f1 FROM test1 ORDER BY f1}} msg] lappend v $msg } {0 {11 33}} do_test select1-4.2 { set v [catch {execsql {SELECT f1 FROM test1 ORDER BY -f1}} msg] lappend v $msg } {0 {33 11}} do_test select1-4.3 { set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1,f2)}} msg] lappend v $msg } {0 {11 33}} do_test select1-4.4 { set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg] lappend v $msg |
︙ | ︙ |