/ 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 Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/func.c.

   836    836     /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function
   837    837     ** is a wrapper around the sqlite3_compileoption_get() C/C++ function.
   838    838     */
   839    839     n = sqlite3_value_int(argv[0]);
   840    840     sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
   841    841   }
   842    842   #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
          843  +
          844  +/*
          845  +** 64-bit byte swap on little-endian platforms.  No-op on bigenidan.
          846  +*/
          847  +static void byteSwap64(unsigned char *x){
          848  +  if( !SQLITE_BIGENDIAN ){
          849  +    unsigned char c;
          850  +    int i;
          851  +    for(i=0; i<4; i++){
          852  +      c = x[i];
          853  +      x[i] = x[7-i];
          854  +      x[7-i] = c;
          855  +    }
          856  +  }
          857  +}
          858  +
          859  +/*
          860  +** The ieee754() function converts a blob into a REAL.  The blob must be
          861  +** an big-endian ieee754 floating point number.
          862  +**
          863  +** Any argument other than an 8-byte blob returns NULL.
          864  +*/
          865  +static void ieee754Func(
          866  +  sqlite3_context *context,
          867  +  int argc,
          868  +  sqlite3_value **argv
          869  +){
          870  +  assert( argc==1 );
          871  +  UNUSED_PARAMETER(argc);
          872  +  if( sqlite3_value_type(argv[0])==SQLITE_BLOB
          873  +   && sqlite3_value_bytes(argv[0])==8
          874  +  ){
          875  +    double r;
          876  +    memcpy(&r, sqlite3_value_blob(argv[0]), 8);
          877  +    byteSwap64((unsigned char*)&r);
          878  +    sqlite3_result_double(context, r);
          879  +  }
          880  +}
   843    881   
   844    882   /* Array for converting from half-bytes (nybbles) into ASCII hex
   845    883   ** digits. */
   846    884   static const char hexdigits[] = {
   847    885     '0', '1', '2', '3', '4', '5', '6', '7',
   848    886     '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 
   849    887   };
................................................................................
   859    897   ** "NULL".  Otherwise, the argument is enclosed in single quotes with
   860    898   ** single-quote escapes.
   861    899   */
   862    900   static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   863    901     assert( argc==1 );
   864    902     UNUSED_PARAMETER(argc);
   865    903     switch( sqlite3_value_type(argv[0]) ){
   866         -    case SQLITE_INTEGER:
   867    904       case SQLITE_FLOAT: {
          905  +      union {
          906  +        double r;
          907  +        unsigned char x[8];
          908  +      } v;
          909  +      sqlite3_int64 vi;
          910  +      int i;
          911  +      char zAns[30];
          912  +      v.r = sqlite3_value_double(argv[0]);
          913  +      vi = (sqlite3_int64)v.r;
          914  +      if( v.r==(double)vi ){
          915  +        sqlite3_result_value(context, argv[0]);
          916  +      }else{
          917  +        byteSwap64(v.x);
          918  +                  /*  0123456789 123456789 12345678 */
          919  +        memcpy(zAns, "ieee754(X'----------------')", 29);
          920  +        for(i=0; i<8; i++){
          921  +          zAns[10+i*2] = hexdigits[v.x[i]>>4];
          922  +          zAns[11+i*2] = hexdigits[v.x[i]&0xf];
          923  +        }
          924  +        sqlite3_result_text(context, zAns, 28, SQLITE_TRANSIENT);
          925  +      }
          926  +      break;
          927  +    }
          928  +    case SQLITE_INTEGER: {
   868    929         sqlite3_result_value(context, argv[0]);
   869    930         break;
   870    931       }
   871    932       case SQLITE_BLOB: {
   872    933         char *zText = 0;
   873    934         char const *zBlob = sqlite3_value_blob(argv[0]);
   874    935         int nBlob = sqlite3_value_bytes(argv[0]);
................................................................................
  1564   1625       FUNCTION(sqlite_version,     0, 0, 0, versionFunc      ),
  1565   1626       FUNCTION(sqlite_source_id,   0, 0, 0, sourceidFunc     ),
  1566   1627       FUNCTION(sqlite_log,         2, 0, 0, errlogFunc       ),
  1567   1628   #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
  1568   1629       FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc  ),
  1569   1630       FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
  1570   1631   #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
         1632  +#ifndef SQLITE_OMIT_FLOATING_POINT
         1633  +    FUNCTION(ieee754,            1, 0, 0, ieee754Func      ),
         1634  +#endif
  1571   1635       FUNCTION(quote,              1, 0, 0, quoteFunc        ),
  1572   1636       FUNCTION(last_insert_rowid,  0, 0, 0, last_insert_rowid),
  1573   1637       FUNCTION(changes,            0, 0, 0, changes          ),
  1574   1638       FUNCTION(total_changes,      0, 0, 0, total_changes    ),
  1575   1639       FUNCTION(replace,            3, 0, 0, replaceFunc      ),
  1576   1640       FUNCTION(zeroblob,           1, 0, 0, zeroblobFunc     ),
  1577   1641     #ifdef SQLITE_SOUNDEX