/ Check-in [f5ad74a9]
Login

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

Overview
Comment:Replace the randomHex() function with separate functions randomBlob() and hex(). (CVS 3620)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f5ad74a9bc57e83c11beb3cf46bb6cd8c9de3f86
User & Date: drh 2007-01-29 17:58:28
Context
2007-01-31
23:37
Fixed incorrect typecast for flock structure ptr in fcntl() call in sqlite3TestLockingStyle() Restored previous fullfsync behavior, try fsync() if fcntl(fd, F_FULLFSYNC, 0) returns an error. (CVS 3621) check-in: f044c5f4 user: aswift tags: trunk
2007-01-29
17:58
Replace the randomHex() function with separate functions randomBlob() and hex(). (CVS 3620) check-in: f5ad74a9 user: drh tags: trunk
15:50
Add the randomhex() function as a built-in. (CVS 3619) check-in: a6001589 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/func.c.

    12     12   ** This file contains the C functions that implement various SQL
    13     13   ** functions of SQLite.  
    14     14   **
    15     15   ** There is only one exported symbol in this file - the function
    16     16   ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
    17     17   ** All other code has file scope.
    18     18   **
    19         -** $Id: func.c,v 1.135 2007/01/29 15:50:06 drh Exp $
           19  +** $Id: func.c,v 1.136 2007/01/29 17:58:28 drh Exp $
    20     20   */
    21     21   #include "sqliteInt.h"
    22     22   #include <ctype.h>
    23     23   /* #include <math.h> */
    24     24   #include <stdlib.h>
    25     25   #include <assert.h>
    26     26   #include "vdbeInt.h"
................................................................................
   269    269     sqlite3Randomness(sizeof(r), &r);
   270    270     if( (r<<1)==0 ) r = 0;  /* Prevent 0x8000.... as the result so that we */
   271    271                             /* can always do abs() of the result */
   272    272     sqlite3_result_int64(context, r);
   273    273   }
   274    274   
   275    275   /*
   276         -** Implementation of randomhex(N).  Return a random hexadecimal string
   277         -** that is N characters long.
          276  +** Implementation of randomblob(N).  Return a random blob
          277  +** that is N bytes long.
   278    278   */
   279         -static void randomHex(
          279  +static void randomBlob(
   280    280     sqlite3_context *context,
   281    281     int argc,
   282    282     sqlite3_value **argv
   283    283   ){
   284         -  int n, i, j;
   285         -  unsigned char c, zBuf[1001];
          284  +  int n;
          285  +  unsigned char *p;
   286    286     assert( argc==1 );
   287    287     n = sqlite3_value_int(argv[0]);
   288         -  if( n&1 ) n++;
   289         -  if( n<2 ) n = 2;
   290         -  if( n>sizeof(zBuf)-1 )  n = sizeof(zBuf)-1;
   291         -  sqlite3Randomness(n/2, zBuf);
   292         -  for(i=n-1, j=n/2-1; i>=1; i-=2, j--){
   293         -    static const char zDigits[] = "0123456789ABCDEF";
   294         -    c = zBuf[j];
   295         -    zBuf[i] = zDigits[c&0xf];
   296         -    zBuf[i-1] = zDigits[c>>4];
   297         -  }
   298         -  zBuf[n] = 0;
   299         -  sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT);
          288  +  if( n<1 ) n = 1;
          289  +  p = sqlite3_malloc(n);
          290  +  sqlite3Randomness(n, p);
          291  +  sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
   300    292   }
   301    293   
   302    294   /*
   303    295   ** Implementation of the last_insert_rowid() SQL function.  The return
   304    296   ** value is the same as the sqlite3_last_insert_rowid() API function.
   305    297   */
   306    298   static void last_insert_rowid(
................................................................................
   571    563     sqlite3_context *context,
   572    564     int argc,
   573    565     sqlite3_value **argv
   574    566   ){
   575    567     sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
   576    568   }
   577    569   
          570  +/* Array for converting from half-bytes (nybbles) into ASCII hex
          571  +** digits. */
          572  +static const char hexdigits[] = {
          573  +  '0', '1', '2', '3', '4', '5', '6', '7',
          574  +  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 
          575  +};
   578    576   
   579    577   /*
   580    578   ** EXPERIMENTAL - This is not an official function.  The interface may
   581    579   ** change.  This function may disappear.  Do not write code that depends
   582    580   ** on this function.
   583    581   **
   584    582   ** Implementation of the QUOTE() function.  This function takes a single
................................................................................
   596    594       }
   597    595       case SQLITE_INTEGER:
   598    596       case SQLITE_FLOAT: {
   599    597         sqlite3_result_value(context, argv[0]);
   600    598         break;
   601    599       }
   602    600       case SQLITE_BLOB: {
   603         -      static const char hexdigits[] = { 
   604         -        '0', '1', '2', '3', '4', '5', '6', '7',
   605         -        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 
   606         -      };
   607    601         char *zText = 0;
   608    602         int nBlob = sqlite3_value_bytes(argv[0]);
   609    603         char const *zBlob = sqlite3_value_blob(argv[0]);
   610    604   
   611    605         zText = (char *)sqliteMalloc((2*nBlob)+4); 
   612    606         if( !zText ){
   613    607           sqlite3_result_error(context, "out of memory", -1);
................................................................................
   644    638         z[j++] = '\'';
   645    639         z[j] = 0;
   646    640         sqlite3_result_text(context, z, j, SQLITE_TRANSIENT);
   647    641         sqliteFree(z);
   648    642       }
   649    643     }
   650    644   }
          645  +
          646  +/*
          647  +** The hex() function.  Interpret the argument as a blob.  Return
          648  +** a hexadecimal rendering as text.
          649  +*/
          650  +static void hexFunc(
          651  +  sqlite3_context *context,
          652  +  int argc,
          653  +  sqlite3_value **argv
          654  +){
          655  +  int i, n;
          656  +  const unsigned char *pBlob;
          657  +  char *zHex, *z;
          658  +  assert( argc==1 );
          659  +  pBlob = sqlite3_value_blob(argv[0]);
          660  +  n = sqlite3_value_bytes(argv[0]);
          661  +  z = zHex = sqlite3_malloc(n*2 + 1);
          662  +  if( zHex==0 ) return;
          663  +  for(i=0; i<n; i++, pBlob++){
          664  +    unsigned char c = *pBlob;
          665  +    *(z++) = hexdigits[(c>>4)&0xf];
          666  +    *(z++) = hexdigits[c&0xf];
          667  +  }
          668  +  *z = 0;
          669  +  sqlite3_result_text(context, zHex, n*2, sqlite3_free);
          670  +}
   651    671   
   652    672   #ifdef SQLITE_SOUNDEX
   653    673   /*
   654    674   ** Compute the soundex encoding of a word.
   655    675   */
   656         -static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
          676  +static void soundexFunc(
          677  +  sqlite3_context *context,
          678  +  int argc,
          679  +  sqlite3_value **argv
          680  +){
   657    681     char zResult[8];
   658    682     const u8 *zIn;
   659    683     int i, j;
   660    684     static const unsigned char iCode[] = {
   661    685       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   662    686       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   663    687       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
................................................................................
  1045   1069       { "round",              1, 0, SQLITE_UTF8,    0, roundFunc  },
  1046   1070       { "round",              2, 0, SQLITE_UTF8,    0, roundFunc  },
  1047   1071       { "upper",              1, 0, SQLITE_UTF8,    0, upperFunc  },
  1048   1072       { "lower",              1, 0, SQLITE_UTF8,    0, lowerFunc  },
  1049   1073       { "coalesce",          -1, 0, SQLITE_UTF8,    0, ifnullFunc },
  1050   1074       { "coalesce",           0, 0, SQLITE_UTF8,    0, 0          },
  1051   1075       { "coalesce",           1, 0, SQLITE_UTF8,    0, 0          },
         1076  +    { "hex",                1, 0, SQLITE_UTF8,    0, hexFunc    },
  1052   1077       { "ifnull",             2, 0, SQLITE_UTF8,    1, ifnullFunc },
  1053   1078       { "random",            -1, 0, SQLITE_UTF8,    0, randomFunc },
  1054         -    { "randomhex",          1, 0, SQLITE_UTF8,    0, randomHex  },
         1079  +    { "randomblob",         1, 0, SQLITE_UTF8,    0, randomBlob },
  1055   1080       { "nullif",             2, 0, SQLITE_UTF8,    1, nullifFunc },
  1056   1081       { "sqlite_version",     0, 0, SQLITE_UTF8,    0, versionFunc},
  1057   1082       { "quote",              1, 0, SQLITE_UTF8,    0, quoteFunc  },
  1058   1083       { "last_insert_rowid",  0, 1, SQLITE_UTF8,    0, last_insert_rowid },
  1059   1084       { "changes",            0, 1, SQLITE_UTF8,    0, changes    },
  1060   1085       { "total_changes",      0, 1, SQLITE_UTF8,    0, total_changes },
  1061   1086   #ifdef SQLITE_SOUNDEX

Changes to test/func.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing built-in functions.
    13     13   #
    14         -# $Id: func.test,v 1.56 2007/01/29 15:50:06 drh Exp $
           14  +# $Id: func.test,v 1.57 2007/01/29 17:58:28 drh Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Create a table to work with.
    20     20   #
    21     21   do_test func-0.0 {
................................................................................
   299    299   do_test func-9.2 {
   300    300     execsql {
   301    301       SELECT typeof(random());
   302    302     }
   303    303   } {integer}
   304    304   do_test func-9.3 {
   305    305     execsql {
   306         -    SELECT randomhex(32) is not null;
          306  +    SELECT randomblob(32) is not null;
   307    307     }
   308    308   } {1}
   309    309   do_test func-9.4 {
   310    310     execsql {
   311         -    SELECT typeof(randomhex(32));
          311  +    SELECT typeof(randomblob(32));
   312    312     }
   313         -} {text}
          313  +} {blob}
   314    314   do_test func-9.5 {
   315    315     execsql {
   316         -    SELECT length(randomhex(32)), length(randomhex(-5)),
   317         -           length(randomhex(2000)), length(randomhex(31));
          316  +    SELECT length(randomblob(32)), length(randomblob(-5)),
          317  +           length(randomblob(2000))
   318    318     }
   319         -} {32 2 1000 32}
          319  +} {32 1 2000}
   320    320   
          321  +# The "hex()" function was added in order to be able to render blobs
          322  +# generated by randomblob().  So this seems like a good place to test
          323  +# hex().
          324  +#
          325  +do_test func-9.10 {
          326  +  execsql {SELECT hex(x'00112233445566778899aAbBcCdDeEfF')}
          327  +} {00112233445566778899AABBCCDDEEFF}
   321    328   
   322    329   # Use the "sqlite_register_test_function" TCL command which is part of
   323    330   # the text fixture in order to verify correct operation of some of
   324    331   # the user-defined SQL function APIs that are not used by the built-in
   325    332   # functions.
   326    333   #
   327    334   set ::DB [sqlite3_connection_pointer db]

Changes to www/lang.tcl.

     1      1   #
     2      2   # Run this Tcl script to generate the lang-*.html files.
     3      3   #
     4         -set rcsid {$Id: lang.tcl,v 1.119 2007/01/29 15:50:06 drh Exp $}
            4  +set rcsid {$Id: lang.tcl,v 1.120 2007/01/29 17:58:28 drh Exp $}
     5      5   source common.tcl
     6      6   
     7      7   if {[llength $argv]>0} {
     8      8     set outputdir [lindex $argv 0]
     9      9   } else {
    10     10     set outputdir ""
    11     11   }
................................................................................
  1278   1278   <tr>
  1279   1279   <td valign="top" align="right">ifnull(<i>X</i>,<i>Y</i>)</td>
  1280   1280   <td valign="top">Return a copy of the first non-NULL argument.  If
  1281   1281   both arguments are NULL then NULL is returned. This behaves the same as 
  1282   1282   <b>coalesce()</b> above.</td>
  1283   1283   </tr>
  1284   1284   
         1285  +<tr>
         1286  +<td valign="top" align="right">hex(<i>X</i>)</td>
         1287  +<td valign="top">The argument is interpreted as a BLOB.  The result
         1288  +is a hexadecimal rendering of the content of that blob.</td>
         1289  +</tr>
         1290  +
  1285   1291   <tr>
  1286   1292   <td valign="top" align="right">last_insert_rowid()</td>
  1287   1293   <td valign="top">Return the ROWID of the last row insert from this
  1288   1294   connection to the database.  This is the same value that would be returned
  1289   1295   from the <b>sqlite_last_insert_rowid()</b> API function.</td>
  1290   1296   </tr>
  1291   1297   
................................................................................
  1370   1376   <tr>
  1371   1377   <td valign="top" align="right">random(*)</td>
  1372   1378   <td valign="top">Return a pseudo-random integer
  1373   1379   between -9223372036854775808 and +9223372036854775807.</td>
  1374   1380   </tr>
  1375   1381   
  1376   1382   <tr>
  1377         -<td valign="top" align="right">randomhex(<i>N</i>)</td>
  1378         -<td valign="top">Return a pseudo-random hexadecimal string that is
  1379         -<i>N</i> characters in length.  <i>N</i> should be an even integer between
  1380         -2 and 1000.  The intended use of this function is to generate
  1381         -universally unique identifiers (UUID).  For that purpose, it is recommended
  1382         -that <i>N</i> be at least 32.</td>
         1383  +<td valign="top" align="right">randomblob(<i>N</i>)</td>
         1384  +<td valign="top">Return a <i>N</i>-byte blob containing pseudo-random bytes.
         1385  +<i>N</i> should be a postive integer.</td>
  1383   1386   </tr>
  1384   1387   
  1385   1388   <tr>
  1386   1389   <td valign="top" align="right">round(<i>X</i>)<br>round(<i>X</i>,<i>Y</i>)</td>
  1387   1390   <td valign="top">Round off the number <i>X</i> to <i>Y</i> digits to the
  1388   1391   right of the decimal point.  If the <i>Y</i> argument is omitted, 0 is 
  1389   1392   assumed.</td>