This patch optimizes the md5_text() function (which is used to

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.
This commit is contained in:
Neil Conway 2005-02-23 22:46:17 +00:00
parent b9a87e5219
commit 3350b3740e
2 changed files with 13 additions and 7 deletions

View 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.
*

View 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);