This patch optimizes the md5_text() function (which is used to
authorNeil Conway <neilc@samurai.com>
Wed, 23 Feb 2005 22:46:17 +0000 (22:46 +0000)
committerNeil Conway <neilc@samurai.com>
Wed, 23 Feb 2005 22:46:17 +0000 (22:46 +0000)
implement the md5() SQL-level function). The old code did the
following:

1. de-toast the datum
2. convert it to a cstring via textout()
3. get the length of the cstring via strlen()

Since we are treating the datum context as a blob of binary data,
the latter two steps are unnecessary. Once the data has been
detoasted, we can just use it as-is, and derive its length from
the varlena metadata.

This patch improves some run-of-the-mill md5() computations by
just under 10% in my limited tests, and passes the regression tests.

I also noticed that md5_text() wasn't checking the return value
of md5_hash(); encountering OOM at precisely the right moment
could result in returning a random md5 hash. This patch corrects
that. A better fix would be to make md5_hash() only return on
success (and/or allocate via palloc()), but since it's used in
the frontend as well I don't see an easy way to do that.

src/backend/libpq/md5.c
src/backend/utils/adt/varlena.c

index 16649abe24f0d1ef52f330d149332cbc82ef321c..3c7fcd6912758a4fb6a7b7915d2fb12a957825a0 100644 (file)
@@ -14,7 +14,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/libpq/md5.c,v 1.27 2004/12/31 21:59:50 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/libpq/md5.c,v 1.28 2005/02/23 22:46:17 neilc Exp $
  */
 
 
@@ -289,8 +289,8 @@ bytesToHex(uint8 b[16], char *s)
  *                       characters.  you thus need to provide an array
  *                       of 33 characters, including the trailing '\0'.
  *
- * RETURNS       0 on failure (out of memory for internal buffers) or
- *               non-zero on success.
+ * RETURNS       false on failure (out of memory for internal buffers) or
+ *               true on success.
  *
  * STANDARDS     MD5 is described in RFC 1321.
  *
index a2570a66bbec68ea659c6cd7d1052f33c1a790e6..26fcab20d359e81ef650de9bad08a2f6293df0ce 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.118 2004/12/31 22:01:22 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.119 2005/02/23 22:46:17 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2310,16 +2310,22 @@ to_hex64(PG_FUNCTION_ARGS)
 Datum
 md5_text(PG_FUNCTION_ARGS)
 {
-   char       *buff = PG_TEXT_GET_STR(PG_GETARG_TEXT_P(0));
-   size_t      len = strlen(buff);
+   text       *in_text = PG_GETARG_TEXT_P(0);
+   size_t      len;
    char       *hexsum;
    text       *result_text;
 
+   /* Calculate the length of the buffer using varlena metadata */
+   len = VARSIZE(in_text) - VARHDRSZ;
+
    /* leave room for the terminating '\0' */
    hexsum = (char *) palloc(MD5_HASH_LEN + 1);
 
    /* get the hash result */
-   md5_hash((void *) buff, len, hexsum);
+   if (md5_hash(VARDATA(in_text), len, hexsum) == false)
+       ereport(ERROR,
+               (errcode(ERRCODE_OUT_OF_MEMORY),
+                errmsg("out of memory")));
 
    /* convert to text and return it */
    result_text = PG_STR_GET_TEXT(hexsum);