From e6170126fc201052b0ec5fc92177eb181d602d26 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 17 Jan 2014 16:52:06 -0500 Subject: [PATCH] Add gen_random_uuid() to contrib/pgcrypto. This function provides a way of generating version 4 (pseudorandom) UUIDs based on pgcrypto's PRNG. The main reason for doing this is that the OSSP UUID library depended on by contrib/uuid-ossp is becoming more and more of a porting headache, so we need an alternative for people who can't install that. A nice side benefit though is that this implementation is noticeably faster than uuid-ossp's uuid_generate_v4() function. Oskari Saarenmaa, reviewed by Emre Hasegeli --- contrib/pgcrypto/Makefile | 2 +- contrib/pgcrypto/pgcrypto--1.0--1.1.sql | 9 +++++++ .../{pgcrypto--1.0.sql => pgcrypto--1.1.sql} | 7 ++++- contrib/pgcrypto/pgcrypto.c | 27 +++++++++++++++++++ contrib/pgcrypto/pgcrypto.control | 2 +- contrib/pgcrypto/pgcrypto.h | 1 + doc/src/sgml/datatype.sgml | 2 ++ doc/src/sgml/pgcrypto.sgml | 11 ++++++++ doc/src/sgml/uuid-ossp.sgml | 9 +++++++ 9 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 contrib/pgcrypto/pgcrypto--1.0--1.1.sql rename contrib/pgcrypto/{pgcrypto--1.0.sql => pgcrypto--1.1.sql} (96%) diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile index dadec953c2..1c85c982ff 100644 --- a/contrib/pgcrypto/Makefile +++ b/contrib/pgcrypto/Makefile @@ -26,7 +26,7 @@ MODULE_big = pgcrypto OBJS = $(SRCS:.c=.o) EXTENSION = pgcrypto -DATA = pgcrypto--1.0.sql pgcrypto--unpackaged--1.0.sql +DATA = pgcrypto--1.1.sql pgcrypto--1.0--1.1.sql pgcrypto--unpackaged--1.0.sql REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \ $(CF_TESTS) \ diff --git a/contrib/pgcrypto/pgcrypto--1.0--1.1.sql b/contrib/pgcrypto/pgcrypto--1.0--1.1.sql new file mode 100644 index 0000000000..42e0c7fffc --- /dev/null +++ b/contrib/pgcrypto/pgcrypto--1.0--1.1.sql @@ -0,0 +1,9 @@ +/* contrib/pgcrypto/pgcrypto--1.0--1.1.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pgcrypto UPDATE TO '1.1'" to load this file. \quit + +CREATE FUNCTION gen_random_uuid() +RETURNS uuid +AS 'MODULE_PATHNAME', 'pg_random_uuid' +LANGUAGE C VOLATILE; diff --git a/contrib/pgcrypto/pgcrypto--1.0.sql b/contrib/pgcrypto/pgcrypto--1.1.sql similarity index 96% rename from contrib/pgcrypto/pgcrypto--1.0.sql rename to contrib/pgcrypto/pgcrypto--1.1.sql index 347825ea07..a260857d30 100644 --- a/contrib/pgcrypto/pgcrypto--1.0.sql +++ b/contrib/pgcrypto/pgcrypto--1.1.sql @@ -1,4 +1,4 @@ -/* contrib/pgcrypto/pgcrypto--1.0.sql */ +/* contrib/pgcrypto/pgcrypto--1.1.sql */ -- complain if script is sourced in psql, rather than via CREATE EXTENSION \echo Use "CREATE EXTENSION pgcrypto" to load this file. \quit @@ -63,6 +63,11 @@ RETURNS bytea AS 'MODULE_PATHNAME', 'pg_random_bytes' LANGUAGE C VOLATILE STRICT; +CREATE FUNCTION gen_random_uuid() +RETURNS uuid +AS 'MODULE_PATHNAME', 'pg_random_uuid' +LANGUAGE C VOLATILE; + -- -- pgp_sym_encrypt(data, key) -- diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c index a441ca77f1..9917e18d86 100644 --- a/contrib/pgcrypto/pgcrypto.c +++ b/contrib/pgcrypto/pgcrypto.c @@ -35,6 +35,7 @@ #include "parser/scansup.h" #include "utils/builtins.h" +#include "utils/uuid.h" #include "px.h" #include "px-crypt.h" @@ -443,6 +444,32 @@ pg_random_bytes(PG_FUNCTION_ARGS) PG_RETURN_BYTEA_P(res); } +/* SQL function: gen_random_uuid() returns uuid */ +PG_FUNCTION_INFO_V1(pg_random_uuid); + +Datum +pg_random_uuid(PG_FUNCTION_ARGS) +{ + uint8 *buf = (uint8 *) palloc(UUID_LEN); + int err; + + /* generate random bits */ + err = px_get_pseudo_random_bytes(buf, UUID_LEN); + if (err < 0) + ereport(ERROR, + (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), + errmsg("Random generator error: %s", px_strerror(err)))); + + /* + * Set magic numbers for a "version 4" (pseudorandom) UUID, see + * http://tools.ietf.org/html/rfc4122#section-4.4 + */ + buf[6] = (buf[6] & 0x0f) | 0x40; /* "version" field */ + buf[8] = (buf[8] & 0x3f) | 0x80; /* "variant" field */ + + PG_RETURN_UUID_P((pg_uuid_t *) buf); +} + static void * find_provider(text *name, PFN provider_lookup, diff --git a/contrib/pgcrypto/pgcrypto.control b/contrib/pgcrypto/pgcrypto.control index 8375cf9e7b..7f79d044ab 100644 --- a/contrib/pgcrypto/pgcrypto.control +++ b/contrib/pgcrypto/pgcrypto.control @@ -1,5 +1,5 @@ # pgcrypto extension comment = 'cryptographic functions' -default_version = '1.0' +default_version = '1.1' module_pathname = '$libdir/pgcrypto' relocatable = true diff --git a/contrib/pgcrypto/pgcrypto.h b/contrib/pgcrypto/pgcrypto.h index 6284ba2406..04ea696ac3 100644 --- a/contrib/pgcrypto/pgcrypto.h +++ b/contrib/pgcrypto/pgcrypto.h @@ -45,5 +45,6 @@ Datum pg_decrypt(PG_FUNCTION_ARGS); Datum pg_encrypt_iv(PG_FUNCTION_ARGS); Datum pg_decrypt_iv(PG_FUNCTION_ARGS); Datum pg_random_bytes(PG_FUNCTION_ARGS); +Datum pg_random_uuid(PG_FUNCTION_ARGS); #endif diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 03863300d4..6bf4cf61d8 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -4015,6 +4015,8 @@ a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11 suited for every application. The module provides functions that implement several standard algorithms. + The module also provides a generation + function for random UUIDs. Alternatively, UUIDs could be generated by client applications or other libraries invoked through a server-side function. diff --git a/doc/src/sgml/pgcrypto.sgml b/doc/src/sgml/pgcrypto.sgml index b99a75c366..31dba8cb73 100644 --- a/doc/src/sgml/pgcrypto.sgml +++ b/doc/src/sgml/pgcrypto.sgml @@ -1084,6 +1084,17 @@ gen_random_bytes(count integer) returns bytea At most 1024 bytes can be extracted at a time. This is to avoid draining the randomness generator pool. + + + gen_random_uuid + + + +gen_random_uuid() returns uuid + + + Returns a version 4 (random) UUID. + diff --git a/doc/src/sgml/uuid-ossp.sgml b/doc/src/sgml/uuid-ossp.sgml index 696cc112dc..c48106ba0f 100644 --- a/doc/src/sgml/uuid-ossp.sgml +++ b/doc/src/sgml/uuid-ossp.sgml @@ -18,6 +18,15 @@ . + + + The OSSP UUID library is not well maintained, and is becoming increasingly + difficult to port to newer platforms. If you only need randomly-generated + (version 4) UUIDs, consider using the gen_random_uuid() + function from the module instead. + + + <literal>uuid-ossp</literal> Functions