Skip to content

Commit 5925e55

Browse files
committed
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
1 parent 565f339 commit 5925e55

File tree

11 files changed

+76
-34
lines changed

11 files changed

+76
-34
lines changed

contrib/pgcrypto/pgcrypto.c

+2-14
Original file line numberDiff line numberDiff line change
@@ -446,20 +446,8 @@ PG_FUNCTION_INFO_V1(pg_random_uuid);
446446
Datum
447447
pg_random_uuid(PG_FUNCTION_ARGS)
448448
{
449-
uint8 *buf = (uint8 *) palloc(UUID_LEN);
450-
451-
/* Generate random bits. */
452-
if (!pg_strong_random(buf, UUID_LEN))
453-
px_THROW_ERROR(PXE_NO_RANDOM);
454-
455-
/*
456-
* Set magic numbers for a "version 4" (pseudorandom) UUID, see
457-
* http://tools.ietf.org/html/rfc4122#section-4.4
458-
*/
459-
buf[6] = (buf[6] & 0x0f) | 0x40; /* "version" field */
460-
buf[8] = (buf[8] & 0x3f) | 0x80; /* "variant" field */
461-
462-
PG_RETURN_UUID_P((pg_uuid_t *) buf);
449+
/* redirect to built-in function */
450+
return gen_random_uuid(fcinfo);
463451
}
464452

465453
static void *

doc/src/sgml/datatype.sgml

+2-10
Original file line numberDiff line numberDiff line change
@@ -4195,16 +4195,8 @@ a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
41954195
</para>
41964196

41974197
<para>
4198-
<productname>PostgreSQL</productname> provides storage and comparison
4199-
functions for UUIDs, but the core database does not include any
4200-
function for generating UUIDs, because no single algorithm is well
4201-
suited for every application. The <xref
4202-
linkend="uuid-ossp"/> module
4203-
provides functions that implement several standard algorithms.
4204-
The <xref linkend="pgcrypto"/> module also provides a generation
4205-
function for random UUIDs.
4206-
Alternatively, UUIDs could be generated by client applications or
4207-
other libraries invoked through a server-side function.
4198+
See <xref linkend="functions-uuid"/> for how to generate a UUID in
4199+
<productname>PostgreSQL</productname>.
42084200
</para>
42094201
</sect1>
42104202

doc/src/sgml/func.sgml

+26
Original file line numberDiff line numberDiff line change
@@ -10267,6 +10267,32 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
1026710267

1026810268
</sect1>
1026910269

10270+
<sect1 id="functions-uuid">
10271+
<title>UUID Functions</title>
10272+
10273+
<indexterm zone="datatype-uuid">
10274+
<primary>UUID</primary>
10275+
<secondary>generating</secondary>
10276+
</indexterm>
10277+
10278+
<indexterm>
10279+
<primary>gen_random_uuid</primary>
10280+
</indexterm>
10281+
10282+
<para>
10283+
<productname>PostgreSQL</productname> includes one function to generate a UUID:
10284+
<synopsis>
10285+
gen_random_uuid() returns uuid
10286+
</synopsis>
10287+
This function returns a version 4 (random) UUID. This is the most commonly
10288+
used type of UUID and is appropriate for most applications.
10289+
</para>
10290+
10291+
<para>
10292+
The <xref linkend="uuid-ossp"/> module provides additional functions that
10293+
implement other standard algorithms for generating UUIDs.
10294+
</para>
10295+
</sect1>
1027010296

1027110297
<sect1 id="functions-xml">
1027210298

doc/src/sgml/pgcrypto.sgml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,8 @@ gen_random_bytes(count integer) returns bytea
11321132
gen_random_uuid() returns uuid
11331133
</synopsis>
11341134
<para>
1135-
Returns a version 4 (random) UUID.
1135+
Returns a version 4 (random) UUID. (Obsolete, this function is now also
1136+
included in core <productname>PostgreSQL</productname>.)
11361137
</para>
11371138
</sect2>
11381139

doc/src/sgml/uuid-ossp.sgml

+3-8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
The <filename>uuid-ossp</filename> module provides functions to generate universally
1212
unique identifiers (UUIDs) using one of several standard algorithms. There
1313
are also functions to produce certain special UUID constants.
14+
This module is only necessary for special requirements beyond what is
15+
available in core <productname>PostgreSQL</productname>. See <xref
16+
linkend="functions-uuid"/> for built-in ways to generate UUIDs.
1417
</para>
1518

1619
<sect2>
@@ -181,14 +184,6 @@ SELECT uuid_generate_v3(uuid_ns_url(), 'http://www.postgresql.org');
181184
More than one of these libraries might be available on a particular
182185
machine, so <filename>configure</filename> does not automatically choose one.
183186
</para>
184-
185-
<note>
186-
<para>
187-
If you only need randomly-generated (version 4) UUIDs,
188-
consider using the <function>gen_random_uuid()</function> function
189-
from the <xref linkend="pgcrypto"/> module instead.
190-
</para>
191-
</note>
192187
</sect2>
193188

194189
<sect2>

src/backend/utils/adt/uuid.c

+20
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,23 @@ uuid_hash_extended(PG_FUNCTION_ARGS)
416416

417417
return hash_any_extended(key->data, UUID_LEN, PG_GETARG_INT64(1));
418418
}
419+
420+
Datum
421+
gen_random_uuid(PG_FUNCTION_ARGS)
422+
{
423+
pg_uuid_t *uuid = palloc(UUID_LEN);
424+
425+
if (!pg_strong_random(uuid, UUID_LEN))
426+
ereport(ERROR,
427+
(errcode(ERRCODE_INTERNAL_ERROR),
428+
errmsg("could not generate random values")));
429+
430+
/*
431+
* Set magic numbers for a "version 4" (pseudorandom) UUID, see
432+
* http://tools.ietf.org/html/rfc4122#section-4.4
433+
*/
434+
uuid->data[6] = (uuid->data[6] & 0x0f) | 0x40; /* time_hi_and_version */
435+
uuid->data[8] = (uuid->data[8] & 0x3f) | 0x80; /* clock_seq_hi_and_reserved */
436+
437+
PG_RETURN_UUID_P(uuid);
438+
}

src/include/catalog/catversion.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 201907141
56+
#define CATALOG_VERSION_NO 201907142
5757

5858
#endif

src/include/catalog/pg_proc.dat

+3
Original file line numberDiff line numberDiff line change
@@ -8376,6 +8376,9 @@
83768376
{ oid => '3412', descr => 'hash',
83778377
proname => 'uuid_hash_extended', prorettype => 'int8',
83788378
proargtypes => 'uuid int8', prosrc => 'uuid_hash_extended' },
8379+
{ oid => '3432', descr => 'generate random UUID',
8380+
proname => 'gen_random_uuid', proleakproof => 't', prorettype => 'uuid',
8381+
proargtypes => '', prosrc => 'gen_random_uuid' },
83798382

83808383
# pg_lsn
83818384
{ oid => '3229', descr => 'I/O',

src/test/regress/expected/opr_sanity.out

+1
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ sha224(bytea)
742742
sha256(bytea)
743743
sha384(bytea)
744744
sha512(bytea)
745+
gen_random_uuid()
745746
starts_with(text,text)
746747
macaddr8_eq(macaddr8,macaddr8)
747748
macaddr8_lt(macaddr8,macaddr8)

src/test/regress/expected/uuid.out

+10
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,15 @@ SELECT COUNT(*) FROM guid1 g1 LEFT JOIN guid2 g2 ON g1.guid_field = g2.guid_fiel
145145
1
146146
(1 row)
147147

148+
-- generation test
149+
TRUNCATE guid1;
150+
INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid());
151+
INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid());
152+
SELECT count(DISTINCT guid_field) FROM guid1;
153+
count
154+
-------
155+
2
156+
(1 row)
157+
148158
-- clean up
149159
DROP TABLE guid1, guid2 CASCADE;

src/test/regress/sql/uuid.sql

+6
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,11 @@ INSERT INTO guid2(guid_field) VALUES('3f3e3c3b3a3039383736353433a2313e');
7575
SELECT COUNT(*) FROM guid1 g1 INNER JOIN guid2 g2 ON g1.guid_field = g2.guid_field;
7676
SELECT COUNT(*) FROM guid1 g1 LEFT JOIN guid2 g2 ON g1.guid_field = g2.guid_field WHERE g2.guid_field IS NULL;
7777

78+
-- generation test
79+
TRUNCATE guid1;
80+
INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid());
81+
INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid());
82+
SELECT count(DISTINCT guid_field) FROM guid1;
83+
7884
-- clean up
7985
DROP TABLE guid1, guid2 CASCADE;

0 commit comments

Comments
 (0)