summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut <peter@eisentraut.org>2019-07-14 14:30:27 +0200
committerPeter Eisentraut <peter@eisentraut.org>2019-07-14 14:30:27 +0200
commit5925e5549890416bcf588334d9d0bc99f8ad6c7f (patch)
tree0b9d6556f5e4dcaa389d2f35cf60804645d2c5f8
parent565f3390005318ea4c982b8d054d56e9fe5a6454 (diff)
downloadpostgresql-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.c16
-rw-r--r--doc/src/sgml/datatype.sgml12
-rw-r--r--doc/src/sgml/func.sgml26
-rw-r--r--doc/src/sgml/pgcrypto.sgml3
-rw-r--r--doc/src/sgml/uuid-ossp.sgml11
-rw-r--r--src/backend/utils/adt/uuid.c20
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_proc.dat3
-rw-r--r--src/test/regress/expected/opr_sanity.out1
-rw-r--r--src/test/regress/expected/uuid.out10
-rw-r--r--src/test/regress/sql/uuid.sql6
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;