diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2019-07-14 14:30:27 +0200 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2019-07-14 14:30:27 +0200 |
commit | 5925e5549890416bcf588334d9d0bc99f8ad6c7f (patch) | |
tree | 0b9d6556f5e4dcaa389d2f35cf60804645d2c5f8 | |
parent | 565f3390005318ea4c982b8d054d56e9fe5a6454 (diff) | |
download | postgresql-5925e5549890416bcf588334d9d0bc99f8ad6c7f.tar.gz |
Add gen_random_uuid function
This adds a built-in function to generate UUIDs.
PostgreSQL hasn't had a built-in function to generate a UUID yet,
relying on external modules such as uuid-ossp and pgcrypto to provide
one. Now that we have a strong random number generator built-in, we
can easily provide a version 4 (random) UUID generation function.
This patch takes the existing function gen_random_uuid() from pgcrypto
and makes it a built-in function. The pgcrypto implementation now
internally redirects to the built-in one.
Reviewed-by: Fabien COELHO <coelho@cri.ensmp.fr>
Discussion: https://www.postgresql.org/message-id/6a65610c-46fc-2323-6b78-e8086340a325@2ndquadrant.com
-rw-r--r-- | contrib/pgcrypto/pgcrypto.c | 16 | ||||
-rw-r--r-- | doc/src/sgml/datatype.sgml | 12 | ||||
-rw-r--r-- | doc/src/sgml/func.sgml | 26 | ||||
-rw-r--r-- | doc/src/sgml/pgcrypto.sgml | 3 | ||||
-rw-r--r-- | doc/src/sgml/uuid-ossp.sgml | 11 | ||||
-rw-r--r-- | src/backend/utils/adt/uuid.c | 20 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.dat | 3 | ||||
-rw-r--r-- | src/test/regress/expected/opr_sanity.out | 1 | ||||
-rw-r--r-- | src/test/regress/expected/uuid.out | 10 | ||||
-rw-r--r-- | src/test/regress/sql/uuid.sql | 6 |
11 files changed, 76 insertions, 34 deletions
diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c index c558767909..f69ae107c3 100644 --- a/contrib/pgcrypto/pgcrypto.c +++ b/contrib/pgcrypto/pgcrypto.c @@ -446,20 +446,8 @@ PG_FUNCTION_INFO_V1(pg_random_uuid); Datum pg_random_uuid(PG_FUNCTION_ARGS) { - uint8 *buf = (uint8 *) palloc(UUID_LEN); - - /* Generate random bits. */ - if (!pg_strong_random(buf, UUID_LEN)) - px_THROW_ERROR(PXE_NO_RANDOM); - - /* - * 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); + /* redirect to built-in function */ + return gen_random_uuid(fcinfo); } static void * diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 35ecd48ed5..9b6d6878eb 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -4195,16 +4195,8 @@ a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11 </para> <para> - <productname>PostgreSQL</productname> provides storage and comparison - functions for UUIDs, but the core database does not include any - function for generating UUIDs, because no single algorithm is well - suited for every application. The <xref - linkend="uuid-ossp"/> module - provides functions that implement several standard algorithms. - The <xref linkend="pgcrypto"/> 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. + See <xref linkend="functions-uuid"/> for how to generate a UUID in + <productname>PostgreSQL</productname>. </para> </sect1> diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index a25c122ac8..c2f5a75ff6 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -10267,6 +10267,32 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple </sect1> + <sect1 id="functions-uuid"> + <title>UUID Functions</title> + + <indexterm zone="datatype-uuid"> + <primary>UUID</primary> + <secondary>generating</secondary> + </indexterm> + + <indexterm> + <primary>gen_random_uuid</primary> + </indexterm> + + <para> + <productname>PostgreSQL</productname> includes one function to generate a UUID: +<synopsis> +gen_random_uuid() returns uuid +</synopsis> + This function returns a version 4 (random) UUID. This is the most commonly + used type of UUID and is appropriate for most applications. + </para> + + <para> + The <xref linkend="uuid-ossp"/> module provides additional functions that + implement other standard algorithms for generating UUIDs. + </para> + </sect1> <sect1 id="functions-xml"> diff --git a/doc/src/sgml/pgcrypto.sgml b/doc/src/sgml/pgcrypto.sgml index 5c79666654..0acd11ed55 100644 --- a/doc/src/sgml/pgcrypto.sgml +++ b/doc/src/sgml/pgcrypto.sgml @@ -1132,7 +1132,8 @@ gen_random_bytes(count integer) returns bytea gen_random_uuid() returns uuid </synopsis> <para> - Returns a version 4 (random) UUID. + Returns a version 4 (random) UUID. (Obsolete, this function is now also + included in core <productname>PostgreSQL</productname>.) </para> </sect2> diff --git a/doc/src/sgml/uuid-ossp.sgml b/doc/src/sgml/uuid-ossp.sgml index b3b816c372..0fbabbfda2 100644 --- a/doc/src/sgml/uuid-ossp.sgml +++ b/doc/src/sgml/uuid-ossp.sgml @@ -11,6 +11,9 @@ The <filename>uuid-ossp</filename> module provides functions to generate universally unique identifiers (UUIDs) using one of several standard algorithms. There are also functions to produce certain special UUID constants. + This module is only necessary for special requirements beyond what is + available in core <productname>PostgreSQL</productname>. See <xref + linkend="functions-uuid"/> for built-in ways to generate UUIDs. </para> <sect2> @@ -181,14 +184,6 @@ SELECT uuid_generate_v3(uuid_ns_url(), 'http://www.postgresql.org'); More than one of these libraries might be available on a particular machine, so <filename>configure</filename> does not automatically choose one. </para> - - <note> - <para> - If you only need randomly-generated (version 4) UUIDs, - consider using the <function>gen_random_uuid()</function> function - from the <xref linkend="pgcrypto"/> module instead. - </para> - </note> </sect2> <sect2> diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c index 09aa6b6daa..589c2d51dd 100644 --- a/src/backend/utils/adt/uuid.c +++ b/src/backend/utils/adt/uuid.c @@ -416,3 +416,23 @@ uuid_hash_extended(PG_FUNCTION_ARGS) return hash_any_extended(key->data, UUID_LEN, PG_GETARG_INT64(1)); } + +Datum +gen_random_uuid(PG_FUNCTION_ARGS) +{ + pg_uuid_t *uuid = palloc(UUID_LEN); + + if (!pg_strong_random(uuid, UUID_LEN)) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("could not generate random values"))); + + /* + * Set magic numbers for a "version 4" (pseudorandom) UUID, see + * http://tools.ietf.org/html/rfc4122#section-4.4 + */ + uuid->data[6] = (uuid->data[6] & 0x0f) | 0x40; /* time_hi_and_version */ + uuid->data[8] = (uuid->data[8] & 0x3f) | 0x80; /* clock_seq_hi_and_reserved */ + + PG_RETURN_UUID_P(uuid); +} diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index e3a6e8dc41..19ccb54796 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201907141 +#define CATALOG_VERSION_NO 201907142 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 762c099e51..0902dce5f1 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -8376,6 +8376,9 @@ { oid => '3412', descr => 'hash', proname => 'uuid_hash_extended', prorettype => 'int8', proargtypes => 'uuid int8', prosrc => 'uuid_hash_extended' }, +{ oid => '3432', descr => 'generate random UUID', + proname => 'gen_random_uuid', proleakproof => 't', prorettype => 'uuid', + proargtypes => '', prosrc => 'gen_random_uuid' }, # pg_lsn { oid => '3229', descr => 'I/O', diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 85af36ee5b..33c058ff51 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -742,6 +742,7 @@ sha224(bytea) sha256(bytea) sha384(bytea) sha512(bytea) +gen_random_uuid() starts_with(text,text) macaddr8_eq(macaddr8,macaddr8) macaddr8_lt(macaddr8,macaddr8) diff --git a/src/test/regress/expected/uuid.out b/src/test/regress/expected/uuid.out index db66dc723e..090103df48 100644 --- a/src/test/regress/expected/uuid.out +++ b/src/test/regress/expected/uuid.out @@ -145,5 +145,15 @@ SELECT COUNT(*) FROM guid1 g1 LEFT JOIN guid2 g2 ON g1.guid_field = g2.guid_fiel 1 (1 row) +-- generation test +TRUNCATE guid1; +INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid()); +INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid()); +SELECT count(DISTINCT guid_field) FROM guid1; + count +------- + 2 +(1 row) + -- clean up DROP TABLE guid1, guid2 CASCADE; diff --git a/src/test/regress/sql/uuid.sql b/src/test/regress/sql/uuid.sql index 518d2b75c0..3bd3b357c7 100644 --- a/src/test/regress/sql/uuid.sql +++ b/src/test/regress/sql/uuid.sql @@ -75,5 +75,11 @@ INSERT INTO guid2(guid_field) VALUES('3f3e3c3b3a3039383736353433a2313e'); SELECT COUNT(*) FROM guid1 g1 INNER JOIN guid2 g2 ON g1.guid_field = g2.guid_field; SELECT COUNT(*) FROM guid1 g1 LEFT JOIN guid2 g2 ON g1.guid_field = g2.guid_field WHERE g2.guid_field IS NULL; +-- generation test +TRUNCATE guid1; +INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid()); +INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid()); +SELECT count(DISTINCT guid_field) FROM guid1; + -- clean up DROP TABLE guid1, guid2 CASCADE; |