SQLite4
Check-in [b55b217f6a]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Further progress on decimal arithmetic.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sqlite4-num
Files: files | file ages | folders
SHA1: b55b217f6a98b255415e5e493fbace3521549ed3
User & Date: dan 2013-05-28 20:33:15
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
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

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, 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;







|







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
...
338
339
340
341
342
343
344


345
346
347
348
349
350
351
...
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
...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
...
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
...
585
586
587
588
589
590
591




592
593
594
595
596
597
598
...
603
604
605
606
607
608
609




610

611
612
613
614
615
616
617
** 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 ){
................................................................................

  /* 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')
................................................................................
    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' ){


      if( c=='0' && nDigit==0 ){



        if( seenRadix && r.e > -(SQLITE4_MX_EXP+1000) ) r.e--;
        continue;
      }

      nDigit++;
      if( nDigit<=18 ){
        r.m = (r.m*10) + c - '0';


        if( seenRadix ) r.e--;





      }else{
        if( c!='0' ) r.approx = 1;
        if( !seenRadix ) r.e++;

      }

    }else if( c=='.' ){
      seenRadix = 1;
    }else if( c=='e' || c=='E' ){
      int exp = 0;
      int expsign = 0;
      int nEDigit = 0;
      if( zIn[i]=='-' ){
................................................................................

finished:
  if( bInvalid && (flags & SQLITE4_PREFIX_ONLY)==0 ){
    r.e = SQLITE4_MX_EXP+1;
    r.m = 0;
  }

  else if( seenRadix==0 && r.e==1 && r.m<=(LARGEST_INT64/10) ){
    r.m = r.m*10;
    r.e = 0;
  }

  return r;
}

/*
** Convert an sqlite4_int64 to a number and return that number.
*/
sqlite4_num sqlite4_num_from_int64(sqlite4_int64 n){
................................................................................
}

/*
** 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){
  char zBuf[24];
  int nOut = 0;
  char *zNum;
  int n;
  static const char zeros[] = "0000000000000000000000000";
  
  if( x.sign && x.m>0 ){
................................................................................
    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);
................................................................................
    removeTrailingZeros(zNum, &n);
    if( n>0 ){
      zOut[0] = '.';
      memcpy(zOut+1, zNum, n);
      nOut += n;
      zOut[n+1] = 0;
    }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);







>
>
>
>


>
>
>
>

>

>






>
>







 







>
>







 







>
>
|
>
>
>
|


>
|
<
<
>
>
|
>
>
>
>
>

<
|
>

>







 







<
<
<
<
<







 







|







 







>
>
>
>







 







>
>
>
>
|
>







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
...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
...
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
...
429
430
431
432
433
434
435





436
437
438
439
440
441
442
...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
...
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
** 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 ){
................................................................................

  /* 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')
................................................................................
    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]=='-' ){
................................................................................

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){
................................................................................
}

/*
** 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 ){
................................................................................
    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);
................................................................................
    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
4121
4122
4123
4124
4125
4126
4127

4128
4129
4130
4131
4132
4133
4134
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*);

/*
** CAPI4REF: Flags For Text-To-Numeric Conversion
*/
#define SQLITE4_PREFIX_ONLY         0x10
#define SQLITE4_IGNORE_WHITESPACE   0x20


typedef struct sqlite4_tokenizer sqlite4_tokenizer;

/*
** CAPI4REF: Register an FTS tokenizer implementation
**
** xTokenize:







|






>







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
400
401
402
403
404
405
406
407
....
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
*/
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);
    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 ){
................................................................................
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;





  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(pIn1->u.num, pIn2->u.num); break;
    default: {
      sqlite4_num_to_int64(pIn1->u.num, &iA);
      sqlite4_num_to_int64(pIn1->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{
    pOut->flags &= ~MEM_TypeMask;
    pOut->flags |= MEM_Real;
    sqlite4VdbeIntegerAffinity(pOut);

  }


  break;

#if 0
  if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
    iA = pIn1->u.i;
    iB = pIn2->u.i;
    switch( pOp->opcode ){







|







 







>













>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
<
<
<
>
|
>
>







393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
....
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
*/
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 ){
................................................................................
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
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);
        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)";
      }







|







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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

  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->n = sqlite4Strlen30(pMem->z);
  pMem->enc = SQLITE4_UTF8;
  pMem->flags |= MEM_Str|MEM_Term;
  sqlite4VdbeChangeEncoding(pMem, enc);
  return rc;
}








<










|







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
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);
        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));







|







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
..
88
89
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
# 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}
................................................................................
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]]
}























































finish_test









>
>







 







|








|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
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
# 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}
................................................................................
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
188
189
190
191
192
193
194
195
  misc5.test misc6.test
  misuse.test
  notnull.test
  null.test
  printf.test 
  quote.test

  savepoint.test savepoint2.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







|







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
52
53
54
55
56
57
58
59
...
146
147
148
149
150
151
152
153
154
  }
} {1024}
wal_check_journal_mode savepoint2-1.1

unset -nocomplain ::sig
unset -nocomplain SQL

set iterations 20

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) {
................................................................................

  # Check that the connection is still running in WAL mode.
  wal_check_journal_mode savepoint2-$ii.7
}

unset -nocomplain ::sig
unset -nocomplain SQL

finish_test







|







 







<
<
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
...
146
147
148
149
150
151
152


  }
} {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) {
................................................................................

  # 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
299
300
301
302
303
304
305
306
307
308
309
310
# 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 {
execsql { PRAGMA vdbe_trace = 1; }
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY -f1}} msg]
  lappend v $msg
} {0 {33 11}}
exit
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







<



<







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