On 2019-04-09 08:04, Peter Eisentraut wrote:
> On 2019-04-08 23:06, Andres Freund wrote:
>> The randomness based UUID generators don't really have dependencies, now
>> that we have a dependency on strong randomness.  I kinda thing the
>> dependency argument actually works *against* uuid-ossp - precisely
>> because of its dependencies (which also vary by OS) it's not a proper
>> replacement for a type of facility a very sizable fraction of our users
>> need.
> 
> Yeah, I think implementing a v4 generator in core would be trivial and
> address almost everyone's requirements.

Here is a proposed patch for this.  I did a fair bit of looking around
in other systems for a naming pattern but didn't find anything
consistent.  So I ended up just taking the function name and code from
pgcrypto.

As you can see, the code is trivial and has no external dependencies.  I
think this would significantly upgrade the usability of the uuid type.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From dec1949a482ae425527987a43d28c8b26ba1e0ed Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 4 Jun 2019 09:00:31 +0200
Subject: [PATCH] Add gen_random_uuid function

---
 doc/src/sgml/datatype.sgml               | 12 ++---------
 doc/src/sgml/func.sgml                   | 26 ++++++++++++++++++++++++
 doc/src/sgml/pgcrypto.sgml               |  3 ++-
 doc/src/sgml/uuid-ossp.sgml              | 11 +++-------
 src/backend/utils/adt/uuid.c             | 20 ++++++++++++++++++
 src/include/catalog/pg_proc.dat          |  3 +++
 src/test/regress/expected/opr_sanity.out |  1 +
 src/test/regress/expected/uuid.out       | 10 +++++++++
 src/test/regress/sql/uuid.sql            |  6 ++++++
 9 files changed, 73 insertions(+), 19 deletions(-)

diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index fc300f605f..809d98036c 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -4175,16 +4175,8 @@ <title><acronym>UUID</acronym> Type</title>
    </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 a79e7c0380..b6caaf6b9b 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -10291,6 +10291,32 @@ <title>Text Search Debugging Functions</title>
 
  </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 @@ <title>Random-Data Functions</title>
 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 @@ <title>uuid-ossp</title>
   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 @@ <title>Building <filename>uuid-ossp</filename></title>
    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/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 87335248a0..8ecf379955 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8341,6 +8341,9 @@
 { oid => '3412', descr => 'hash',
   proname => 'uuid_hash_extended', prorettype => 'int8',
   proargtypes => 'uuid int8', prosrc => 'uuid_hash_extended' },
+{ oid => '3429', 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 @@ CREATE UNIQUE INDEX guid1_unique_BTREE ON guid1 USING BTREE 
(guid_field);
 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;
-- 
2.21.0

Reply via email to