]> granicus.if.org Git - postgresql/commitdiff
Add gen_random_uuid function
authorPeter Eisentraut <peter@eisentraut.org>
Sun, 14 Jul 2019 12:30:27 +0000 (14:30 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Sun, 14 Jul 2019 12:30:27 +0000 (14:30 +0200)
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

contrib/pgcrypto/pgcrypto.c
doc/src/sgml/datatype.sgml
doc/src/sgml/func.sgml
doc/src/sgml/pgcrypto.sgml
doc/src/sgml/uuid-ossp.sgml
src/backend/utils/adt/uuid.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.dat
src/test/regress/expected/opr_sanity.out
src/test/regress/expected/uuid.out
src/test/regress/sql/uuid.sql

index c558767909888aefdb7c402f3061cdda5c1795d8..f69ae107c3a741e3543f866d28adc1a570c526e4 100644 (file)
@@ -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 *
index 35ecd48ed5d442e5dd43a0db8868d0c0232abc4e..9b6d6878eb054a33af1123dc4fae4c9f438fd451 100644 (file)
@@ -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>
 
index a25c122ac8f5a18c530443ed9bbfb5b8729e5670..c2f5a75ff67f9c68f8d2be205d19d903e808d4b7 100644 (file)
@@ -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">
 
index 5c796666543469bdd019543960290b021c7d3fb1..0acd11ed555dd0e9520a098b7a63f1451993c9ae 100644 (file)
@@ -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>
 
index b3b816c372572d4881a3b726b68aecf51d4517a5..0fbabbfda246054554c47bcbb2f67a4220e3b9f6 100644 (file)
@@ -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>
index 09aa6b6daab197ee21d55f5fd7396cfcae20146a..589c2d51dde1acf41dd8b670d9abe6552fda4eac 100644 (file)
@@ -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);
+}
index e3a6e8dc410204f7575870150e651d78837d7554..19ccb54796b0aa07533b6478df749f1159c34871 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201907141
+#define CATALOG_VERSION_NO     201907142
 
 #endif
index 762c099e516f7f259de3a41fcf0c6670261f6cfc..0902dce5f140c963deee8671dc5aa70b6f44f07b 100644 (file)
 { 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',
index 85af36ee5bca2f8010642647f3bf49ac03a04249..33c058ff514ed05aedb48bab64df4a73fde9f1ff 100644 (file)
@@ -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)
index db66dc723efc55e0373448503cd9dc2762588be8..090103df48ab6e9010ac27885063be7048b4e002 100644 (file)
@@ -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;
index 518d2b75c00fb88e94d4a0860c617d4d97c02527..3bd3b357c77cfb1e1f2a1eb3f3be8db437c7bb44 100644 (file)
@@ -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;