mirror of
https://github.com/postgres/postgres.git
synced 2026-07-08 17:20:57 -04:00
Allow explicit casting between bytea and uuid.
This enables the use of functions such as encode() and decode() with UUID values, allowing them to be converted to and from alternative formats like base64 or hex. The cast maps the 16-byte internal representation of a UUID directly to a bytea datum. This is more efficient than going through a text forepresentation. Bump catalog version. Author: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> Co-authored-by: Aleksander Alekseev <aleksander@tigerdata.com> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru> Reviewed-by: Jelte Fennema-Nio <postgres@jeltef.nl> Discussion: https://postgr.es/m/CAJ7c6TOramr1UTLcyB128LWMqita1Y7%3Darq3KHaU%3Dqikf5yKOQ%40mail.gmail.com
This commit is contained in:
parent
1811f1af98
commit
ba21f5bf8a
7 changed files with 79 additions and 1 deletions
|
|
@ -4439,6 +4439,17 @@ a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
|
|||
Output is always in the standard form.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is possible to cast <type>uuid</type> values to and from type
|
||||
<type>bytea</type>. This is useful for using functions such as
|
||||
<function>encode()</function> and <function>decode()</function>
|
||||
with UUID values. For example:
|
||||
<programlisting>
|
||||
encode('1ea3d64c-bc40-4cc3-84bb-6b11ee31e5c2'::uuid::bytea, 'base64')
|
||||
decode('HqPWTLxATMOEu2sR7jHlwg==', 'base64')::uuid
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
See <xref linkend="functions-uuid"/> for how to generate a UUID in
|
||||
<productname>PostgreSQL</productname>.
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "utils/guc.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/sortsupport.h"
|
||||
#include "utils/uuid.h"
|
||||
#include "varatt.h"
|
||||
|
||||
/* GUC variable */
|
||||
|
|
@ -1340,3 +1341,29 @@ int8_bytea(PG_FUNCTION_ARGS)
|
|||
{
|
||||
return int8send(fcinfo);
|
||||
}
|
||||
|
||||
/* Cast bytea -> uuid */
|
||||
Datum
|
||||
bytea_uuid(PG_FUNCTION_ARGS)
|
||||
{
|
||||
bytea *v = PG_GETARG_BYTEA_PP(0);
|
||||
int len = VARSIZE_ANY_EXHDR(v);
|
||||
pg_uuid_t *uuid;
|
||||
|
||||
if (len != UUID_LEN)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||
errmsg("invalid input length for type %s", "uuid"),
|
||||
errdetail("Expected %d bytes, got %d.", UUID_LEN, len)));
|
||||
|
||||
uuid = palloc_object(pg_uuid_t);
|
||||
memcpy(uuid->data, VARDATA_ANY(v), UUID_LEN);
|
||||
PG_RETURN_UUID_P(uuid);
|
||||
}
|
||||
|
||||
/* Cast uuid -> bytea; can just use uuid_send() */
|
||||
Datum
|
||||
uuid_bytea(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return uuid_send(fcinfo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,6 @@
|
|||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 202603171
|
||||
#define CATALOG_VERSION_NO 202603191
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -362,6 +362,12 @@
|
|||
{ castsource => 'bytea', casttarget => 'int8', castfunc => 'int8(bytea)',
|
||||
castcontext => 'e', castmethod => 'f' },
|
||||
|
||||
# Allow explicit coercions between bytea and uuid type
|
||||
{ castsource => 'bytea', casttarget => 'uuid', castfunc => 'uuid(bytea)',
|
||||
castcontext => 'e', castmethod => 'f' },
|
||||
{ castsource => 'uuid', casttarget => 'bytea', castfunc => 'bytea(uuid)',
|
||||
castcontext => 'e', castmethod => 'f' },
|
||||
|
||||
# Allow explicit coercions between int4 and "char"
|
||||
{ castsource => 'char', casttarget => 'int4', castfunc => 'int4(char)',
|
||||
castcontext => 'e', castmethod => 'f' },
|
||||
|
|
|
|||
|
|
@ -1208,6 +1208,13 @@
|
|||
proname => 'int8', prorettype => 'int8', proargtypes => 'bytea',
|
||||
prosrc => 'bytea_int8' },
|
||||
|
||||
{ oid => '9880', descr => 'convert uuid to bytea',
|
||||
proname => 'bytea', prorettype => 'bytea', proargtypes => 'uuid',
|
||||
prosrc => 'uuid_bytea' },
|
||||
{ oid => '9881', descr => 'convert bytea to uuid',
|
||||
proname => 'uuid', prorettype => 'uuid', proargtypes => 'bytea',
|
||||
prosrc => 'bytea_uuid' },
|
||||
|
||||
{ oid => '449', descr => 'hash',
|
||||
proname => 'hashint2', prorettype => 'int4', proargtypes => 'int2',
|
||||
prosrc => 'hashint2' },
|
||||
|
|
|
|||
|
|
@ -305,5 +305,27 @@ SELECT uuid_extract_timestamp('11111111-1111-1111-1111-111111111111'); -- null
|
|||
|
||||
(1 row)
|
||||
|
||||
-- casts
|
||||
SELECT '5b35380a-7143-4912-9b55-f322699c6770'::uuid::bytea;
|
||||
bytea
|
||||
------------------------------------
|
||||
\x5b35380a714349129b55f322699c6770
|
||||
(1 row)
|
||||
|
||||
SELECT '\x019a2f859ced7225b99d9c55044a2563'::bytea::uuid;
|
||||
uuid
|
||||
--------------------------------------
|
||||
019a2f85-9ced-7225-b99d-9c55044a2563
|
||||
(1 row)
|
||||
|
||||
SELECT '\x1234567890abcdef'::bytea::uuid; -- error
|
||||
ERROR: invalid input length for type uuid
|
||||
DETAIL: Expected 16 bytes, got 8.
|
||||
SELECT v = v::bytea::uuid as matched FROM gen_random_uuid() v;
|
||||
matched
|
||||
---------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
-- clean up
|
||||
DROP TABLE guid1, guid2, guid3 CASCADE;
|
||||
|
|
|
|||
|
|
@ -146,6 +146,11 @@ SELECT uuid_extract_timestamp('017F22E2-79B0-7CC3-98C4-DC0C0C07398F') = 'Tuesday
|
|||
SELECT uuid_extract_timestamp(gen_random_uuid()); -- null
|
||||
SELECT uuid_extract_timestamp('11111111-1111-1111-1111-111111111111'); -- null
|
||||
|
||||
-- casts
|
||||
SELECT '5b35380a-7143-4912-9b55-f322699c6770'::uuid::bytea;
|
||||
SELECT '\x019a2f859ced7225b99d9c55044a2563'::bytea::uuid;
|
||||
SELECT '\x1234567890abcdef'::bytea::uuid; -- error
|
||||
SELECT v = v::bytea::uuid as matched FROM gen_random_uuid() v;
|
||||
|
||||
-- clean up
|
||||
DROP TABLE guid1, guid2, guid3 CASCADE;
|
||||
|
|
|
|||
Loading…
Reference in a new issue