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
This commit is contained in:
parent
565f339000
commit
5925e55498
|
@ -446,20 +446,8 @@ PG_FUNCTION_INFO_V1(pg_random_uuid);
|
||||||
Datum
|
Datum
|
||||||
pg_random_uuid(PG_FUNCTION_ARGS)
|
pg_random_uuid(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
uint8 *buf = (uint8 *) palloc(UUID_LEN);
|
/* redirect to built-in function */
|
||||||
|
return gen_random_uuid(fcinfo);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
|
|
|
@ -4195,16 +4195,8 @@ a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<productname>PostgreSQL</productname> provides storage and comparison
|
See <xref linkend="functions-uuid"/> for how to generate a UUID in
|
||||||
functions for UUIDs, but the core database does not include any
|
<productname>PostgreSQL</productname>.
|
||||||
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.
|
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
|
@ -10267,6 +10267,32 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
|
||||||
|
|
||||||
</sect1>
|
</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">
|
<sect1 id="functions-xml">
|
||||||
|
|
||||||
|
|
|
@ -1132,7 +1132,8 @@ gen_random_bytes(count integer) returns bytea
|
||||||
gen_random_uuid() returns uuid
|
gen_random_uuid() returns uuid
|
||||||
</synopsis>
|
</synopsis>
|
||||||
<para>
|
<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>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
The <filename>uuid-ossp</filename> module provides functions to generate universally
|
The <filename>uuid-ossp</filename> module provides functions to generate universally
|
||||||
unique identifiers (UUIDs) using one of several standard algorithms. There
|
unique identifiers (UUIDs) using one of several standard algorithms. There
|
||||||
are also functions to produce certain special UUID constants.
|
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>
|
</para>
|
||||||
|
|
||||||
<sect2>
|
<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
|
More than one of these libraries might be available on a particular
|
||||||
machine, so <filename>configure</filename> does not automatically choose one.
|
machine, so <filename>configure</filename> does not automatically choose one.
|
||||||
</para>
|
</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>
|
||||||
|
|
||||||
<sect2>
|
<sect2>
|
||||||
|
|
|
@ -416,3 +416,23 @@ uuid_hash_extended(PG_FUNCTION_ARGS)
|
||||||
|
|
||||||
return hash_any_extended(key->data, UUID_LEN, PG_GETARG_INT64(1));
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -53,6 +53,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 201907141
|
#define CATALOG_VERSION_NO 201907142
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8376,6 +8376,9 @@
|
||||||
{ oid => '3412', descr => 'hash',
|
{ oid => '3412', descr => 'hash',
|
||||||
proname => 'uuid_hash_extended', prorettype => 'int8',
|
proname => 'uuid_hash_extended', prorettype => 'int8',
|
||||||
proargtypes => 'uuid int8', prosrc => 'uuid_hash_extended' },
|
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
|
# pg_lsn
|
||||||
{ oid => '3229', descr => 'I/O',
|
{ oid => '3229', descr => 'I/O',
|
||||||
|
|
|
@ -742,6 +742,7 @@ sha224(bytea)
|
||||||
sha256(bytea)
|
sha256(bytea)
|
||||||
sha384(bytea)
|
sha384(bytea)
|
||||||
sha512(bytea)
|
sha512(bytea)
|
||||||
|
gen_random_uuid()
|
||||||
starts_with(text,text)
|
starts_with(text,text)
|
||||||
macaddr8_eq(macaddr8,macaddr8)
|
macaddr8_eq(macaddr8,macaddr8)
|
||||||
macaddr8_lt(macaddr8,macaddr8)
|
macaddr8_lt(macaddr8,macaddr8)
|
||||||
|
|
|
@ -145,5 +145,15 @@ SELECT COUNT(*) FROM guid1 g1 LEFT JOIN guid2 g2 ON g1.guid_field = g2.guid_fiel
|
||||||
1
|
1
|
||||||
(1 row)
|
(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
|
-- clean up
|
||||||
DROP TABLE guid1, guid2 CASCADE;
|
DROP TABLE guid1, guid2 CASCADE;
|
||||||
|
|
|
@ -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 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;
|
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
|
-- clean up
|
||||||
DROP TABLE guid1, guid2 CASCADE;
|
DROP TABLE guid1, guid2 CASCADE;
|
||||||
|
|
Loading…
Reference in New Issue