/ Check-in [87597e98]
Login

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

Overview
Comment:Add the ieee754() SQL function that interprets a blob as a big-endian double. Arrange for the quote() SQL function to emit ieee754() functions in its output so that floating-point values in the database are exactly preserved by a ".dump" command in the shell.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | ieee754-func
Files: files | file ages | folders
SHA1: 87597e988fc6aad00e1326c152830a0938d30457
User & Date: drh 2012-06-18 14:23:06
Context
2012-06-18
14:23
Add the ieee754() SQL function that interprets a blob as a big-endian double. Arrange for the quote() SQL function to emit ieee754() functions in its output so that floating-point values in the database are exactly preserved by a ".dump" command in the shell. Closed-Leaf check-in: 87597e98 user: drh tags: ieee754-func
2012-06-16
15:26
In Lemon, when comparing the output to the *.h file to see if it has changed, make sure that the proposed new output and the preexisting output are the same size before deciding that they are the same. check-in: 0c2fb18d user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/func.c.

836
837
838
839
840
841
842






































843
844
845
846
847
848
849
...
859
860
861
862
863
864
865
866























867
868
869
870
871
872
873
874
....
1564
1565
1566
1567
1568
1569
1570



1571
1572
1573
1574
1575
1576
1577
  /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function
  ** is a wrapper around the sqlite3_compileoption_get() C/C++ function.
  */
  n = sqlite3_value_int(argv[0]);
  sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */







































/* Array for converting from half-bytes (nybbles) into ASCII hex
** digits. */
static const char hexdigits[] = {
  '0', '1', '2', '3', '4', '5', '6', '7',
  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 
};
................................................................................
** "NULL".  Otherwise, the argument is enclosed in single quotes with
** single-quote escapes.
*/
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  switch( sqlite3_value_type(argv[0]) ){
    case SQLITE_INTEGER:























    case SQLITE_FLOAT: {
      sqlite3_result_value(context, argv[0]);
      break;
    }
    case SQLITE_BLOB: {
      char *zText = 0;
      char const *zBlob = sqlite3_value_blob(argv[0]);
      int nBlob = sqlite3_value_bytes(argv[0]);
................................................................................
    FUNCTION(sqlite_version,     0, 0, 0, versionFunc      ),
    FUNCTION(sqlite_source_id,   0, 0, 0, sourceidFunc     ),
    FUNCTION(sqlite_log,         2, 0, 0, errlogFunc       ),
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
    FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc  ),
    FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */



    FUNCTION(quote,              1, 0, 0, quoteFunc        ),
    FUNCTION(last_insert_rowid,  0, 0, 0, last_insert_rowid),
    FUNCTION(changes,            0, 0, 0, changes          ),
    FUNCTION(total_changes,      0, 0, 0, total_changes    ),
    FUNCTION(replace,            3, 0, 0, replaceFunc      ),
    FUNCTION(zeroblob,           1, 0, 0, zeroblobFunc     ),
  #ifdef SQLITE_SOUNDEX







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







 







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







 







>
>
>







836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
...
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
....
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
  /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function
  ** is a wrapper around the sqlite3_compileoption_get() C/C++ function.
  */
  n = sqlite3_value_int(argv[0]);
  sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */

/*
** 64-bit byte swap on little-endian platforms.  No-op on bigenidan.
*/
static void byteSwap64(unsigned char *x){
  if( !SQLITE_BIGENDIAN ){
    unsigned char c;
    int i;
    for(i=0; i<4; i++){
      c = x[i];
      x[i] = x[7-i];
      x[7-i] = c;
    }
  }
}

/*
** The ieee754() function converts a blob into a REAL.  The blob must be
** an big-endian ieee754 floating point number.
**
** Any argument other than an 8-byte blob returns NULL.
*/
static void ieee754Func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  if( sqlite3_value_type(argv[0])==SQLITE_BLOB
   && sqlite3_value_bytes(argv[0])==8
  ){
    double r;
    memcpy(&r, sqlite3_value_blob(argv[0]), 8);
    byteSwap64((unsigned char*)&r);
    sqlite3_result_double(context, r);
  }
}

/* Array for converting from half-bytes (nybbles) into ASCII hex
** digits. */
static const char hexdigits[] = {
  '0', '1', '2', '3', '4', '5', '6', '7',
  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 
};
................................................................................
** "NULL".  Otherwise, the argument is enclosed in single quotes with
** single-quote escapes.
*/
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  switch( sqlite3_value_type(argv[0]) ){
    case SQLITE_FLOAT: {
      union {
        double r;
        unsigned char x[8];
      } v;
      sqlite3_int64 vi;
      int i;
      char zAns[30];
      v.r = sqlite3_value_double(argv[0]);
      vi = (sqlite3_int64)v.r;
      if( v.r==(double)vi ){
        sqlite3_result_value(context, argv[0]);
      }else{
        byteSwap64(v.x);
                  /*  0123456789 123456789 12345678 */
        memcpy(zAns, "ieee754(X'----------------')", 29);
        for(i=0; i<8; i++){
          zAns[10+i*2] = hexdigits[v.x[i]>>4];
          zAns[11+i*2] = hexdigits[v.x[i]&0xf];
        }
        sqlite3_result_text(context, zAns, 28, SQLITE_TRANSIENT);
      }
      break;
    }
    case SQLITE_INTEGER: {
      sqlite3_result_value(context, argv[0]);
      break;
    }
    case SQLITE_BLOB: {
      char *zText = 0;
      char const *zBlob = sqlite3_value_blob(argv[0]);
      int nBlob = sqlite3_value_bytes(argv[0]);
................................................................................
    FUNCTION(sqlite_version,     0, 0, 0, versionFunc      ),
    FUNCTION(sqlite_source_id,   0, 0, 0, sourceidFunc     ),
    FUNCTION(sqlite_log,         2, 0, 0, errlogFunc       ),
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
    FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc  ),
    FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
#ifndef SQLITE_OMIT_FLOATING_POINT
    FUNCTION(ieee754,            1, 0, 0, ieee754Func      ),
#endif
    FUNCTION(quote,              1, 0, 0, quoteFunc        ),
    FUNCTION(last_insert_rowid,  0, 0, 0, last_insert_rowid),
    FUNCTION(changes,            0, 0, 0, changes          ),
    FUNCTION(total_changes,      0, 0, 0, total_changes    ),
    FUNCTION(replace,            3, 0, 0, replaceFunc      ),
    FUNCTION(zeroblob,           1, 0, 0, zeroblobFunc     ),
  #ifdef SQLITE_SOUNDEX