SQLite

Check-in [ea0e32828f]
Login

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

Overview
Comment:better handling of exponential notation (CVS 145)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ea0e32828f5643eeb00b216a287d14f4826ddf2d
User & Date: drh 2000-09-14 01:21:10.000
Context
2000-09-14
01:25
Version 1.0.5 (CVS 495) (check-in: 84839d8764 user: drh tags: trunk)
01:21
better handling of exponential notation (CVS 145) (check-in: ea0e32828f user: drh tags: trunk)
2000-08-28
16:25
Version 1.0.4 (CVS 496) (check-in: 92346e003e user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to VERSION.
1
1.0.4
|
1
1.0.5
Changes to src/util.c.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.14 2000/07/31 11:57:37 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

#ifdef MEMORY_DEBUG








|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.15 2000/09/14 01:21:10 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

#ifdef MEMORY_DEBUG

545
546
547
548
549
550
551



































552
553
554
555
556
557
558
559

560
561

562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597

598
599
600
601































602
603
604
605
606
607
608
    }
    case 5: {
      result = cb - ca;
    };
  }
  return result;
}




































/* This comparison routine is what we use for comparison operations
** in an SQL expression.  (Ex:  name<'Hello' or value<5).  Compare two
** strings.  Use case only as a tie-breaker.  Numbers compare in
** numerical order.
*/
int sqliteCompare(const char *atext, const char *btext){
  int result;

  result = privateStrCmp(atext, btext, 0);
  if( result==0 ) result = privateStrCmp(atext, btext, 1);

  return result;
}

/*
** If you compile just this one file with the -DTEST_COMPARE=1 option,
** it generates a program to test the comparisons routines.  
*/
#ifdef TEST_COMPARE
#include <stdlib.h>
#include <stdio.h>
int sortCmp(const char **a, const char **b){
  return sqliteCompare(*a, *b);
}
int main(int argc, char **argv){
  int i, j, k, n;
  static char *azStr[] = {
     "abc", "aBc", "abcd", "aBcd", 
     "123", "124", "1234", "-123", "-124", "-1234", 
     "123.45", "123.456", "123.46", "-123.45", "-123.46", "-123.456", 
     "x9", "x10", "x-9", "x-10", "X9", "X10",

  };
  n = sizeof(azStr)/sizeof(azStr[0]);
  qsort(azStr, n, sizeof(azStr[0]), sortCmp);
  for(i=0; i<n; i++){
    printf("%s\n", azStr[i]);
  }
  printf("Sanity1...");
  fflush(stdout);

  for(i=0; i<n-1; i++){
    char *a = azStr[i];
    for(j=i+1; j<n; j++){
      char *b = azStr[j];
      if( sqliteCompare(a,b) != -sqliteCompare(b,a) ){
        printf("Failed!  \"%s\" vs \"%s\"\n", a, b);
        i = j = n;
      }

    }
  }
  if( i<n ){
    printf(" OK\n");































  }
  return 0;
}
#endif

/*
** This routine is used for sorting.  Each key is a list of one or more







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








>
|
|
>














|


|


>








>








>



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







545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
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
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
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
    }
    case 5: {
      result = cb - ca;
    };
  }
  return result;
}

/*
** Do a comparison of pure numerics.  If either string is not a pure
** numeric, then return 0.  Otherwise return 1 and set *pResult to be
** negative, zero or positive if the first string are numerially less than
** equal to, or greater than the second.
*/
static int privateCompareNum(const char *a, const char *b, int *pResult){
  char *endPtr;
  double rA, rB;
  int isNumA, isNumB;
  if( isdigit(*a) || ((*a=='-' || *a=='+') && isdigit(a[1])) ){
    rA = strtod(a, &endPtr);
    isNumA = *endPtr==0;
  }else{
    isNumA = 0;
  }
  if( isdigit(*b) || ((*b=='-' || *b=='+') && isdigit(b[1])) ){
    rB = strtod(b, &endPtr);
    isNumB = *endPtr==0;
  }else{
    isNumB = 0;
  }
  if( isNumB==0 && isNumA==0 ) return 0;
  if( isNumA!=isNumB ){
    *pResult =  isNumA - isNumB;
  }else if( rA<rB ){
    *pResult = -1;
  }else if( rA>rB ){
    *pResult = 1;
  }else{
    *pResult = 0;
  }
  return 1;
}

/* This comparison routine is what we use for comparison operations
** in an SQL expression.  (Ex:  name<'Hello' or value<5).  Compare two
** strings.  Use case only as a tie-breaker.  Numbers compare in
** numerical order.
*/
int sqliteCompare(const char *atext, const char *btext){
  int result;
  if( !privateCompareNum(atext, btext, &result) || result==0 ){
    result = privateStrCmp(atext, btext, 0);
    if( result==0 ) result = privateStrCmp(atext, btext, 1);
  }
  return result;
}

/*
** If you compile just this one file with the -DTEST_COMPARE=1 option,
** it generates a program to test the comparisons routines.  
*/
#ifdef TEST_COMPARE
#include <stdlib.h>
#include <stdio.h>
int sortCmp(const char **a, const char **b){
  return sqliteCompare(*a, *b);
}
int main(int argc, char **argv){
  int i, j, k, n, cnt;
  static char *azStr[] = {
     "abc", "aBc", "abcd", "aBcd", 
     "123", "124", "1234", "-123", "-124", "-1234", "+124",
     "123.45", "123.456", "123.46", "-123.45", "-123.46", "-123.456", 
     "x9", "x10", "x-9", "x-10", "X9", "X10",
     "1.234e+02", "+123", "1.23E2", "1.2345e+2", "-1.2345e2", "+w"
  };
  n = sizeof(azStr)/sizeof(azStr[0]);
  qsort(azStr, n, sizeof(azStr[0]), sortCmp);
  for(i=0; i<n; i++){
    printf("%s\n", azStr[i]);
  }
  printf("Sanity1...");
  fflush(stdout);
  cnt = 0;
  for(i=0; i<n-1; i++){
    char *a = azStr[i];
    for(j=i+1; j<n; j++){
      char *b = azStr[j];
      if( sqliteCompare(a,b) != -sqliteCompare(b,a) ){
        printf("Failed!  \"%s\" vs \"%s\"\n", a, b);
        i = j = n;
      }
      cnt++;
    }
  }
  if( i<n ){
    printf(" OK (%d)\n", cnt);
  }
  printf("Sanity2...");
  fflush(stdout);
  cnt = 0;
  for(i=0; i<n; i++){
    char *a = azStr[i];
    for(j=0; j<n; j++){
      char *b = azStr[j];
      for(k=0; k<n; k++){
        char *c = azStr[k];
        int x1, x2, x3, success;
        x1 = sqliteCompare(a,b);
        x2 = sqliteCompare(b,c);
        x3 = sqliteCompare(a,c);
        if( x1==0 ){
          success = x2==x3;
        }else if( x1<0 ){
          success = (x2<=0 && x3<=0) || x2>0;
        }else{
          success = (x2>=0 && x3>=0) || x2<0;
        }
        if( !success ){
          printf("Failed!  \"%s\" vs \"%s\" vs \"%s\"\n", a, b, c);
          i = j = k = n+1;
        }
        cnt++;
      }
    }
  }
  if( i<n+1 ){
    printf(" OK (%d)\n", cnt);
  }
  return 0;
}
#endif

/*
** This routine is used for sorting.  Each key is a list of one or more
Changes to src/vdbe.c.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.40 2000/08/28 16:22:00 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.41 2000/09/14 01:21:10 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
*/
#define Stringify(P,I) \
   ((P->aStack[I].flags & STK_Str)==0 ? hardStringify(P,I) : 0)
static int hardStringify(Vdbe *p, int i){
  char zBuf[30];
  int fg = p->aStack[i].flags;
  if( fg & STK_Real ){
    sprintf(zBuf,"%g",p->aStack[i].r);
  }else if( fg & STK_Int ){
    sprintf(zBuf,"%d",p->aStack[i].i);
  }else{
    p->zStack[i] = "";
    p->aStack[i].n = 1;
    p->aStack[i].flags |= STK_Str;
    return 0;







|







543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
*/
#define Stringify(P,I) \
   ((P->aStack[I].flags & STK_Str)==0 ? hardStringify(P,I) : 0)
static int hardStringify(Vdbe *p, int i){
  char zBuf[30];
  int fg = p->aStack[i].flags;
  if( fg & STK_Real ){
    sprintf(zBuf,"%.15g",p->aStack[i].r);
  }else if( fg & STK_Int ){
    sprintf(zBuf,"%d",p->aStack[i].i);
  }else{
    p->zStack[i] = "";
    p->aStack[i].n = 1;
    p->aStack[i].flags |= STK_Str;
    return 0;
Changes to test/expr.test.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing expressions.
#
# $Id: expr.test,v 1.8 2000/06/16 20:51:26 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing expressions.
#
# $Id: expr.test,v 1.9 2000/09/14 01:21:11 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
test_expr expr-1.35 {i1=1, i2=2} {i1-i2=-1} {1}
test_expr expr-1.36 {i1=1, i2=0} {not i1} {0}
test_expr expr-1.37 {i1=1, i2=NULL} {not i2} {1}

test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782
test_expr expr-2.4 {r1=1.23, r2=2.34} {r1/r2} 0.525641
test_expr expr-2.5 {r1=1.23, r2=2.34} {r2/r1} 1.90244
test_expr expr-2.6 {r1=1.23, r2=2.34} {r2<r1} 0
test_expr expr-2.7 {r1=1.23, r2=2.34} {r2<=r1} 0
test_expr expr-2.8 {r1=1.23, r2=2.34} {r2>r1} 1
test_expr expr-2.9 {r1=1.23, r2=2.34} {r2>=r1} 1
test_expr expr-2.10 {r1=1.23, r2=2.34} {r2!=r1} 1
test_expr expr-2.11 {r1=1.23, r2=2.34} {r2=r1} 0
test_expr expr-2.12 {r1=1.23, r2=2.34} {r2<>r1} 1







|
|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
test_expr expr-1.35 {i1=1, i2=2} {i1-i2=-1} {1}
test_expr expr-1.36 {i1=1, i2=0} {not i1} {0}
test_expr expr-1.37 {i1=1, i2=NULL} {not i2} {1}

test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782
test_expr expr-2.4 {r1=1.23, r2=2.34} {r1/r2} 0.525641025641026
test_expr expr-2.5 {r1=1.23, r2=2.34} {r2/r1} 1.90243902439024
test_expr expr-2.6 {r1=1.23, r2=2.34} {r2<r1} 0
test_expr expr-2.7 {r1=1.23, r2=2.34} {r2<=r1} 0
test_expr expr-2.8 {r1=1.23, r2=2.34} {r2>r1} 1
test_expr expr-2.9 {r1=1.23, r2=2.34} {r2>=r1} 1
test_expr expr-2.10 {r1=1.23, r2=2.34} {r2!=r1} 1
test_expr expr-2.11 {r1=1.23, r2=2.34} {r2=r1} 0
test_expr expr-2.12 {r1=1.23, r2=2.34} {r2<>r1} 1
Changes to www/changes.tcl.
12
13
14
15
16
17
18







19
20
21
22
23
24
25
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}








chng {2000 Aug 28 (Version 1.0.4)} {
<li>Added functions <b>length()</b> and <b>substr()</b>.</li>
<li>Fix a bug in the <b>sqlite</b> shell program that was causing
    a coredump when the output mode was "column" and the first row
    of data contained a NULL.</li>
}







>
>
>
>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}

chng {2000 Sep 13 (Version 1.0.5)} {
<li>Changed the print format for floating point values from "%g" to "%.15g".
    </li>
<li>Changed the comparison function so that numbers in exponential notation
    (ex: 1.234e+05) sort in numerical order.</li>
}

chng {2000 Aug 28 (Version 1.0.4)} {
<li>Added functions <b>length()</b> and <b>substr()</b>.</li>
<li>Fix a bug in the <b>sqlite</b> shell program that was causing
    a coredump when the output mode was "column" and the first row
    of data contained a NULL.</li>
}