]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the ieee754() SQL function that interprets a blob as a big-endian double. ieee754-func
authordrh <drh@noemail.net>
Mon, 18 Jun 2012 14:23:06 +0000 (14:23 +0000)
committerdrh <drh@noemail.net>
Mon, 18 Jun 2012 14:23:06 +0000 (14:23 +0000)
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.

FossilOrigin-Name: 87597e988fc6aad00e1326c152830a0938d30457

manifest
manifest.uuid
src/func.c

index 1043803b950876deb2bf42916ae0d802a6705995..b55e0e3b9cfd940c0c69dcd0bf8cfd8003dca0f5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C In\sLemon,\swhen\scomparing\sthe\soutput\sto\sthe\s*.h\sfile\sto\ssee\sif\sit\shas\schanged,\nmake\ssure\sthat\sthe\sproposed\snew\soutput\sand\sthe\spreexisting\soutput\sare\sthe\nsame\ssize\sbefore\sdeciding\sthat\sthey\sare\sthe\ssame.
-D 2012-06-16T15:26:31.082
+C Add\sthe\sieee754()\sSQL\sfunction\sthat\sinterprets\sa\sblob\sas\sa\sbig-endian\sdouble.\nArrange\sfor\sthe\squote()\sSQL\sfunction\sto\semit\sieee754()\sfunctions\sin\sits\soutput\nso\sthat\sfloating-point\svalues\sin\sthe\sdatabase\sare\sexactly\spreserved\sby\sa\n".dump"\scommand\sin\sthe\sshell.
+D 2012-06-18T14:23:06.889
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in d17fddaa4e81f93a7c9c7c0808aacb3fc95f79f4
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -135,7 +135,7 @@ F src/delete.c 4c20ea4f6213b3bc1c6a510586864b679946e05e
 F src/expr.c 06a7733d19dc725dc46ba51afd9feadb4b85d991
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
-F src/func.c c6b3c94320253a35bda43fb69cc292618e3285d6
+F src/func.c fab8831959557d4668decd4114da5686c5919d42
 F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b
 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
@@ -1005,7 +1005,10 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P f5b5a13f7394dc143aa136f1d4faba6839eaa6dc
-R 1f8bdd1a411e91223aef9522ba34a3e6
+P 0c2fb18d25217ada7e75dcab8b342bbc632875d8
+R a69dd6288fa77a5b1431e7d5145e0a60
+T *branch * ieee754-func
+T *sym-ieee754-func *
+T -sym-trunk *
 U drh
-Z 53f96406b6eec20edfa4ee33fc7d7346
+Z f2065a600167b98e49c11fee712be824
index 0425283c1801b4c2bc8ced768caef967efae97a3..913bcd027599be3f3e33d068231d7b7fca9b901b 100644 (file)
@@ -1 +1 @@
-0c2fb18d25217ada7e75dcab8b342bbc632875d8
\ No newline at end of file
+87597e988fc6aad00e1326c152830a0938d30457
\ No newline at end of file
index 6ffc7184b0404568f44f183d0fad21c414d020e8..137ed36114e2b8ebd7066d7aad537f6d3a546cda 100644 (file)
@@ -841,6 +841,44 @@ static void compileoptiongetFunc(
 }
 #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[] = {
@@ -863,8 +901,31 @@ 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: {
+      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;
     }
@@ -1568,6 +1629,9 @@ void sqlite3RegisterGlobalFunctions(void){
     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          ),