Thread

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Add base32hex support to encode() and decode() functions.

  2. Allow explicit casting between bytea and uuid.

  3. Add support for base64url encoding and decoding

  1. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Aleksander Alekseev <aleksander@tigerdata.com> — 2025-10-23T09:55:01Z

    Hi Sergey,
    
    > I'm writing to propose adding two new built-in functions to PostgreSQL that provide compact UUID encoding using the base32hex format.
    
    Firstly, cc:'ing a few dozens of people is not the best way to get
    attention to your patch. Please don't do this.
    
    Secondly, in order to propose a patch please use `git format-patch`
    and send it as an attachment. Then register it on the nearest open
    commitfest [1].
    
    The interface you are proposing is ugly and is not composable. The
    right way of doing this IMO would be:
    
    1. Implement uuid -> bytea and bytea -> uuid casting
    2. Implement encode(bytea, 'base32') and decode(text, 'base32')
    
    So the overall interface should be like this:
    
    SELECT encode(uuidv7() :: bytea, 'base32');
    
    The value of converting uuid to base32 is not obvious though, so I
    would recommend explaining it in more detail. Consider starting a new
    thread for each separate patch.
    
    [1]: https://commitfest.postgresql.org/
    -- 
    Best regards,
    Aleksander Alekseev
    
    
    
    
  2. Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-23T12:34:43Z

    Hi pgsql-hackers,
    I'm writing to propose adding two new built-in functions to PostgreSQL that provide compact UUID encoding using the base32hex format.
    I'm one of the contributors to RFC 9562 (UUIDs) and to the uuidv7() implementations in PostgreSQL and several libraries. I'm writing to express my strong support for a new patch by Andrey Borodin, the developer of the built-in uuidv7() function for PostgreSQL 18. This patch adds two new functions for UUID compact text representation. These functions would be long-awaited additions to PostgreSQL's UUID functionality.
    I would like to request the community to review this patch and to consider it for commit.
    The patch is available here: https://github.com/x4m/postgres_g/commit/aa902bbc5dfc47d4b35f05016304a1e671abb505 
    _______________________________
    uuid_to_base32hex ( uuid ) -> text
    Encodes a UUID into a 26-character base32hex string (uppercase, no hyphens, without padding), using the alphabet 0123456789ABCDEFGHIJKLMNOPQRSTUV as specified in RFC 4648 (https://datatracker.ietf.org/doc/html/rfc4648#page-10).
    To accommodate base32hex encoding (5 bits per character), the 128-bit UUID requires 130 bits total (26 characters * 5 bits). The additional 2 zero bits are appended as padding.
    This compact, lexicographically sortable format preserves temporal ordering for UUIDv7, making it ideal for primary keys stored as values in JSON key-value pairs, as well as for URLs, filenames, and other space-constrained contexts.
    Example:uuid_to_base32hex('019535d9-3df7-79fb-b466-fa907fa17f9e'::uuid) -> 06AJBM9TUTSVND36VA87V8BVJO_______________________________
    base32hex_to_uuid ( text ) -> uuid
    Decodes a base32hex string back into its original UUID. The input is case-insensitive. Invalid inputs return NULL. The decoding is lossless and produces a bitwise-identical UUID.
    Example:base32hex_to_uuid('06AJBM9TUTSVND36VA87V8BVJO') -> 019535d9-3df7-79fb-b466-fa907fa17f9e_______________________________
    We considered base36 but rejected it due to poor performance. Crockford's Base32 was also rejected due to its lack of native support in standard libraries, making base32hex the most practical choice.
    Converter: https://tomeko.net/online_tools/base32hex.php?lang=en
    
    Best regards,Sergey Prokhorenko
    
    
    
    
    
    
  3. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Andrey Borodin <x4mmm@yandex-team.ru> — 2025-10-23T13:06:43Z

    Hello!
    
    > On 23 Oct 2025, at 14:55, Aleksander Alekseev <aleksander@tigerdata.com> wrote:
    > 
    > Secondly, in order to propose a patch please use `git format-patch`
    > and send it as an attachment. Then register it on the nearest open
    > commitfest [1].
    
    I think it's not about review yet, but more of a discussing viability and general approach.
    The code itself is trivial in this case.
    
    My first reaction was very skeptical too. Yes, this representation (28V4APV8JC9D792M89J185Q000) seems more developer-friendly than default (123e4567-e89b-12d3-a456-426614174000). But why should we bother with propagating one data format over another?
    
    Yet, this format is RFC-blessed. It makes sense to consider providing an alternative to unfriendly format.
    
    > The interface you are proposing is ugly and is not composable. The
    > right way of doing this IMO would be:
    > 
    > 1. Implement uuid -> bytea and bytea -> uuid casting
    > 2. Implement encode(bytea, 'base32') and decode(text, 'base32')
    > 
    > So the overall interface should be like this:
    > 
    > SELECT encode(uuidv7() :: bytea, 'base32');
    
    That's an excellent feedback! Would such conversion be idiomatic for Postgres users?
    Are there any other alternative approaches?
    
    > The value of converting uuid to base32 is not obvious though, so I
    > would recommend explaining it in more detail.
    
    Yes, and maybe some examples of other systems that adopted this format would be handy too. Sergey, can you, please, extend reasoning why this particular format is prominent? RFC 4648 describes a bunch of formats.
    
    > Consider starting a new
    > thread for each separate patch.
    
    I think this thread is fine for discussing.
    
    Thank you!
    
    
    Best regards, Andrey Borodin.
    
    
    
  4. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Jelte Fennema-Nio <postgres@jeltef.nl> — 2025-10-23T14:10:04Z

    On Thu, 23 Oct 2025 at 15:07, Andrey Borodin <x4mmm@yandex-team.ru> wrote:
    > > SELECT encode(uuidv7() :: bytea, 'base32');
    >
    > That's an excellent feedback! Would such conversion be idiomatic for Postgres users?
    > Are there any other alternative approaches?
    
    Agreed that extending the encode function is the way to go. An example
    of that is the recently added support for base64url:
    https://git.postgresql.org/cgit/postgresql.git/commit/?h=REL_18_0&id=e1d917182c1953b16b32a39ed2fe38e3d0823047
    
    > > The value of converting uuid to base32 is not obvious though, so I
    > > would recommend explaining it in more detail.
    >
    > Yes, and maybe some examples of other systems that adopted this format would be handy too. Sergey, can you, please, extend reasoning why this particular format is prominent? RFC 4648 describes a bunch of formats.
    
    I've definitely used base32 to encode uuids myself. The primary
    benefit being shorter strings, while still being able to spell them
    out by voice to people without having to specify whether a letter is
    upper or lowercase.
    
    
    
    
  5. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Aleksander Alekseev <aleksander@tigerdata.com> — 2025-10-23T15:08:29Z

    Hi,
    
    > > I'm writing to propose adding two new built-in functions to PostgreSQL that provide compact UUID encoding using the base32hex format.
    >
    > Firstly, cc:'ing a few dozens of people is not the best way to get
    > attention to your patch. Please don't do this.
    >
    > [...]
    
    I checked pgsql-hackers@ archive [1] and if I understand correctly
    Sergey is not on the mailing list. So people that were not cc:'ed
    didn't receive his e-mail. I attached the original text for those
    interested and also for history.
    
    Sergey, please make sure you are subscribed to the mailing list [2].
    
    [1]: https://www.postgresql.org/message-id/CAJ7c6TOramr1UTLcyB128LWMqita1Y7%3Darq3KHaU%3Dqikf5yKOQ%40mail.gmail.com
    [2]: https://www.postgresql.org/list/
    
    -- 
    Best regards,
    Aleksander Alekseev
    
  6. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-23T17:34:13Z

    >> The value of converting uuid to base32 is not obvious though, so I>> would recommend explaining it in more detail.
    
    > Yes, and maybe some examples of other systems that adopted this format would be handy too.
    
    DNSSEC (https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions)
    many encoders and decoders
    > Sergey, can you, please, extend reasoning why this particular format is prominent? RFC 4648 describes a bunch of formats.
    
    > Best regards, Andrey Borodin.
    
    
    Base32hex:1. Preserves sort order (unlike base64)2. Compact3. Standardized and therefore implemented consistently everywhere4. Implemented in many programming languages' standard libraries5. Does not require specifying character case during dictation6. Has simple and high-performance encoding and decoding algorithms (necessary for system integration using JSON)
    The only compact text encoding eliminates the problem of incompatibility. The authors and contributors of RFC 9562 were categorically against having multiple encodings for UUIDs. They wanted to have only one compact, sort-order-preserving text encoding. For compatibility, they added the canonical UUID format. Due to time constraints, the compact encoding was not included in RFC 9562.
    In databases, UUIDs should preferably be stored in binary format (the UUID type in PostgreSQL) according to RFC 9562.
    Intermediate formats (bytea) reduce performance, which is the very reason we even abandoned the more compact base36 encoding.
    
    
    
    
      
  7. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-23T21:00:50Z

    On Thu, Oct 23, 2025 at 10:34 AM Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    >
    > >> The value of converting uuid to base32 is not obvious though, so I
    > >> would recommend explaining it in more detail.
    >
    > > Yes, and maybe some examples of other systems that adopted this format would be handy too.
    >
    > DNSSEC (https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions)
    > many encoders and decoders
    >
    > > Sergey, can you, please, extend reasoning why this particular format is prominent? RFC 4648 describes a bunch of formats.
    >
    >
    > > Best regards, Andrey Borodin.
    >
    >
    > Base32hex:
    > 1. Preserves sort order (unlike base64)
    > 2. Compact
    > 3. Standardized and therefore implemented consistently everywhere
    > 4. Implemented in many programming languages' standard libraries
    > 5. Does not require specifying character case during dictation
    > 6. Has simple and high-performance encoding and decoding algorithms (necessary for system integration using JSON)
    >
    > The only compact text encoding eliminates the problem of incompatibility. The authors and contributors of RFC 9562 were categorically against having multiple encodings for UUIDs. They wanted to have only one compact, sort-order-preserving text encoding. For compatibility, they added the canonical UUID format. Due to time constraints, the compact encoding was not included in RFC 9562.
    >
    > In databases, UUIDs should preferably be stored in binary format (the UUID type in PostgreSQL) according to RFC 9562.
    >
    > Intermediate formats (bytea) reduce performance, which is the very reason we even abandoned the more compact base36 encoding.
    
    Given that what uuid_to_base32hex() actually does is encoding the
    input UUID,  I find that it could be confusing if we have a similar
    function other than encode() function. Also, we could end up
    introducing as many encoding and decoding functions dedicated for UUID
    as we want to support encoding methods, bloating the functions.
    
    So as the first step, +1 for supporting base32hex for encode() and
    decode() functions and supporting the UUID <-> bytea conversion. I
    believe it would cover most use cases and the cost of UUID <-> bytea
    conversion is negligible.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  8. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-23T22:45:48Z

    > Given that what uuid_to_base32hex() actually does is encoding theinput UUID,  I find that it could be confusing if we have a similar
    function other than encode() function. Also, we could end up
    introducing as many encoding and decoding functions dedicated for UUID
    as we want to support encoding methods, bloating the functions.
    
    > So as the first step, +1 for supporting base32hex for encode() and
    decode() functions and supporting the UUID <-> bytea conversion. I
    believe it would cover most use cases and the cost of UUID <-> bytea
    conversion is negligible.
    
    > Regards,
    
    > -- 
    > Masahiko Sawada
    > Amazon Web Services: https://aws.amazon.com
    
    
    Masahiko,
    I see you're in favor of base32hex encoding. That's great!
    Your arguments make sense, and I generally support enhancing the standard encode() and decode() functions to handle base32hex. It seems like the right approach from a developer experience standpoint.
    However, I'm unclear about some implementation aspects. Why add conversions between UUID and bytea data types? Wouldn't that require creating dedicated UUID <-> bytea conversion functions? Instead, could we implement encode() as polymorphic to handle UUID type inputs directly? For decode(), we'd need  some way (a parameter?) to specify the UUID output type instead of bytea. Another option would be automatic type casting when inserting bytea data into UUID columns. Neither an extra parameter nor additional type casting seems ideal to me, though I don't have better alternatives. But actually, for a short UUID text encoding to succeed, it's more important that it becomes the single, de facto standard. We should avoid supporting multiple encodings, just as the authors and contributors of RFC 9562 did: https://github.com/uuid6/new-uuid-encoding-techniques-ietf-draft/discussions/17#discussioncomment-10614817    Therefore, whenever possible, encode() and decode() should support just one UUID text encoding, namely base32hex.
    Best regards,Sergey Prokhorenko
    
    
    
      
  9. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-24T04:57:55Z

    On Thu, Oct 23, 2025 at 3:46 PM Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    >
    > > Given that what uuid_to_base32hex() actually does is encoding the
    > input UUID,  I find that it could be confusing if we have a similar
    > function other than encode() function. Also, we could end up
    > introducing as many encoding and decoding functions dedicated for UUID
    > as we want to support encoding methods, bloating the functions.
    >
    > > So as the first step, +1 for supporting base32hex for encode() and
    > decode() functions and supporting the UUID <-> bytea conversion. I
    > believe it would cover most use cases and the cost of UUID <-> bytea
    > conversion is negligible.
    >
    > > Regards,
    >
    > > --
    > > Masahiko Sawada
    > > Amazon Web Services: https://aws.amazon.com
    >
    >
    > Masahiko,
    >
    > I see you're in favor of base32hex encoding. That's great!
    >
    > Your arguments make sense, and I generally support enhancing the standard encode() and decode() functions to handle base32hex. It seems like the right approach from a developer experience standpoint.
    >
    > However, I'm unclear about some implementation aspects. Why add conversions between UUID and bytea data types? Wouldn't that require creating dedicated UUID <-> bytea conversion functions? Instead, could we implement encode() as polymorphic to handle UUID type inputs directly? For decode(), we'd need  some way (a parameter?) to specify the UUID output type instead of bytea. Another option would be automatic type casting when inserting bytea data into UUID columns. Neither an extra parameter nor additional type casting seems ideal to me, though I don't have better alternatives.
    
    While we can implement something like decode(uuid, text), I don't
    think we can implement decode() in the way you proposed unless I'm
    missing something.
    
    I think the conversion support between UUID and bytea is useful in
    general, not limited to encode()/decode() support. And users would be
    able to create wrapper functions if they don't want to add casting for
    every encode() and decode() calls. For example,
    
    create function uuid_to_base32(uuid) returns text language sql immutable strict
    begin atomic
        select encode($1::bytea, 'base32hex');
    end;
    
    Since such functions are inlineable, the different between executing
    encode(uuid_data::bytea, 'base32hex') and encode(uuid_data,
    'base32hex') would only be the conversion; one palloc and one memcpy.
    
    > But actually, for a short UUID text encoding to succeed, it's more important that it becomes the single, de facto standard. We should avoid supporting multiple encodings, just as the authors and contributors of RFC 9562 did: https://github.com/uuid6/new-uuid-encoding-techniques-ietf-draft/discussions/17#discussioncomment-10614817    Therefore, whenever possible, encode() and decode() should support just one UUID text encoding, namely base32hex.
    
    I guess it's ultimately the developer's choice, no? For example, if
    they are using multiple databases (or data processing platforms) in
    their system and 'hex' is the only encoding that all components can
    encode and decode, they might choose 'hex' encoding.
    
    Regards,
    
    --
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  10. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-24T07:16:41Z

    On Thu, Oct 23, 2025 at 3:46 PM Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    >
    > > Given that what uuid_to_base32hex() actually does is encoding the
    > input UUID,  I find that it could be confusing if we have a similar
    > function other than encode() function. Also, we could end up
    > introducing as many encoding and decoding functions dedicated for UUID
    > as we want to support encoding methods, bloating the functions.
    >
    > > So as the first step, +1 for supporting base32hex for encode() and
    > decode() functions and supporting the UUID <-> bytea conversion. I
    > believe it would cover most use cases and the cost of UUID <-> bytea
    > conversion is negligible.
    >
    > > Regards,
    >
    > > --
    > > Masahiko Sawada
    > > Amazon Web Services: https://aws.amazon.com
    >
    >
    > Masahiko,
    >
    > I see you're in favor of base32hex encoding. That's great!
    >
    > Your arguments make sense, and I generally support enhancing the standard encode() and decode() functions to handle base32hex. It seems like the right approach from a developer experience standpoint.
    >
    > However, I'm unclear about some implementation aspects. Why add conversions between UUID and bytea data types? Wouldn't that require creating dedicated UUID <-> bytea conversion functions? Instead, could we implement encode() as polymorphic to handle UUID type inputs directly? For decode(), we'd need  some way (a parameter?) to specify the UUID output type instead of bytea. Another option would be automatic type casting when inserting bytea data into UUID columns. Neither an extra parameter nor additional type casting seems ideal to me, though I don't have better alternatives.
    
    While we can implement something like decode(uuid, text), I don't
    think we can implement decode() in the way you proposed unless I'm
    missing something.
    
    I think the conversion support between UUID and bytea is useful in
    general, not limited to encode()/decode() support. And users would be
    able to create wrapper functions if they don't want to add casting for
    every encode() and decode() calls. For example,
    
    create function uuid_to_base32(uuid) returns text language sql immutable strict
    begin atomic
        select encode($1::bytea, 'base32hex');
    end;
    
    Since such functions are inlineable, the different between executing
    encode(uuid_data::bytea, 'base32hex') and encode(uuid_data,
    'base32hex') would only be the conversion; one palloc and one memcpy.
    
    > But actually, for a short UUID text encoding to succeed, it's more important that it becomes the single, de facto standard. We should avoid supporting multiple encodings, just as the authors and contributors of RFC 9562 did: https://github.com/uuid6/new-uuid-encoding-techniques-ietf-draft/discussions/17#discussioncomment-10614817    Therefore, whenever possible, encode() and decode() should support just one UUID text encoding, namely base32hex.
    
    I guess it's ultimately the developer's choice, no? For example, if
    they are using multiple databases (or data processing platforms) in
    their system and 'hex' is the only encoding that all components can
    encode and decode, they might choose 'hex' encoding.
    
    Regards,
    
    --
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    ____________________________________________
    
    
    Masahiko,
    Developers will still be able to use the long canonical 'hex' UUID format for compatibility. But the short format is not a developer choice, but a convention. We mustn't allow a situation where 25% of systems use base32hex, 25% use Crocksford's Base32, 25% use base36, and 25% even use erroneously sorted base64. That's a very real nightmare. You, too, have every reason not to want to increase the number of built-in functions in PostgreSQL.
     But here is a solution that I hope will satisfy everyone:
    
    encode('019535d9-3df7-79fb-b466-​fa907fa17f9e', 'uuid_to_base32hex') -> 06AJBM9TUTSVND36VA87V8BVJOdecode('06AJBM9TUTSVND36VA87V8BVJO', 'base32hex_to_uuid') -> 019535d9-3df7-79fb-b466-​fa907fa17f9e
    I don't see any real business need for UUID <-> bytea conversions.
    Best regards,Sergey Prokhorenko
    
    
    
    
    
    
    
    
    
      
  11. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-24T18:23:23Z

    On Fri, Oct 24, 2025 at 12:17 AM Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    >
    >
    > Masahiko,
    >
    > Developers will still be able to use the long canonical 'hex' UUID format for compatibility. But the short format is not a developer choice, but a convention. We mustn't allow a situation where 25% of systems use base32hex, 25% use Crocksford's Base32, 25% use base36, and 25% even use erroneously sorted base64. That's a very real nightmare. You, too, have every reason not to want to increase the number of built-in functions in PostgreSQL.
    >
    > But here is a solution that I hope will satisfy everyone:
    >
    > encode('019535d9-3df7-79fb-b466-fa907fa17f9e', 'uuid_to_base32hex') -> 06AJBM9TUTSVND36VA87V8BVJO
    
    Does it mean the first argument is uuid type data and when
    'uuid_to_base32hex' is specified as the format the function requires a
    uuid data at the first argument? I could not understand the difference
    between specifying 'based32hex' and 'uuid_to_base32hex' when encoding
    UUID data with base32hex encoding.
    
    > decode('06AJBM9TUTSVND36VA87V8BVJO', 'base32hex_to_uuid') -> 019535d9-3df7-79fb-b466-fa907fa17f9e
    
    Suppose that the decode() takes text data at the first argument and
    returns UUID data, the function signature would be decode(text, text)
    -> uuid. But we cannot create two functions that have the same name
    and the same argument types.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  12. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-24T22:39:45Z

    
        On Friday 24 October 2025 at 09:24:15 pm GMT+3, Masahiko Sawada <sawada.mshk@gmail.com> wrote:  
     
     On Fri, Oct 24, 2025 at 12:17 AM Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    >
    >
    > Masahiko,
    >
    > Developers will still be able to use the long canonical 'hex' UUID format for compatibility. But the short format is not a developer choice, but a convention. We mustn't allow a situation where 25% of systems use base32hex, 25% use Crocksford's Base32, 25% use base36, and 25% even use erroneously sorted base64. That's a very real nightmare. You, too, have every reason not to want to increase the number of built-in functions in PostgreSQL.
    >
    > But here is a solution that I hope will satisfy everyone:
    >
    > encode('019535d9-3df7-79fb-b466-fa907fa17f9e', 'uuid_to_base32hex') -> 06AJBM9TUTSVND36VA87V8BVJO
    
    > Does it mean the first argument is uuid type data and when
    > 'uuid_to_base32hex' is specified as the format the function requires a
    > uuid data at the first argument?
    
    Yes, that's right.PostgreSQL will automatically cast the string '019535d9-3df7-79fb-b466-fa907fa17f9e' to the uuid type, since the format is correct.
    
    
    > I could not understand the difference
    > between specifying 'based32hex' and 'uuid_to_base32hex' when encoding
    > UUID data with base32hex encoding.
    
    
    1. Specifying 'based32hex' in encode function means the first parameter is of bytea type as usual. 
    
    
    But specifying 'uuid_to_base32hex' means the first parameter is of uuid type.
    
    
    2. The encode function does not yet support format based32hex. Therefore, it is not known whether padding ===== should be used.
    But padding ===== is not used when specifying 'uuid_to_base32hex'.
    
    
    > decode('06AJBM9TUTSVND36VA87V8BVJO', 'base32hex_to_uuid') -> 019535d9-3df7-79fb-b466-fa907fa17f9e
    
    > Suppose that the decode() takes text data at the first argument and
    > returns UUID data, the function signature would be decode(text, text)
    > -> uuid. But we cannot create two functions that have the same name
    > and the same argument types.
    Yes, you're right. This is a problem that can't be solved without composite return values. We clearly took the wrong approach by coupling UUID conversion with encode/decode functions, which only apply to bytea. UUID and bytea are fundamentally different data types. Meanwhile, PostgreSQL has over 30 other type conversion functions that deal with other data types. For example, array_to_string, string_to_array, jsonb_to_record, to_char, to_timestamp, and to_hex. In this situation, the best solution would be to revert to the original uuid_to_base32hex() and base32hex_to_uuid() functions rather than deal with type incompatibility issues.
    
    
    > Regards,
    
    > -- 
    > Masahiko Sawada
    > Amazon Web Services: https://aws.amazon.com
    
    
      
  13. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-24T23:31:25Z

    On Fri, Oct 24, 2025 at 3:42 PM Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    >
    >
    >
    > On Friday 24 October 2025 at 09:24:15 pm GMT+3, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    >
    > On Fri, Oct 24, 2025 at 12:17 AM Sergey Prokhorenko
    > <sergeyprokhorenko@yahoo.com.au> wrote:
    > >
    > >
    > > Masahiko,
    > >
    > > Developers will still be able to use the long canonical 'hex' UUID format for compatibility. But the short format is not a developer choice, but a convention. We mustn't allow a situation where 25% of systems use base32hex, 25% use Crocksford's Base32, 25% use base36, and 25% even use erroneously sorted base64. That's a very real nightmare. You, too, have every reason not to want to increase the number of built-in functions in PostgreSQL.
    > >
    > > But here is a solution that I hope will satisfy everyone:
    > >
    > > encode('019535d9-3df7-79fb-b466-fa907fa17f9e', 'uuid_to_base32hex') -> 06AJBM9TUTSVND36VA87V8BVJO
    >
    > > Does it mean the first argument is uuid type data and when
    > > 'uuid_to_base32hex' is specified as the format the function requires a
    > > uuid data at the first argument?
    >
    > Yes, that's right.
    > PostgreSQL will automatically cast the string '019535d9-3df7-79fb-b466-fa907fa17f9e' to the uuid type, since the format is correct.
    >
    >
    > > I could not understand the difference
    > > between specifying 'based32hex' and 'uuid_to_base32hex' when encoding
    > > UUID data with base32hex encoding.
    >
    >
    > 1. Specifying 'based32hex' in encode function means the first parameter is of bytea type as usual.
    >
    >
    > But specifying 'uuid_to_base32hex' means the first parameter is of uuid type.
    >
    >
    > 2. The encode function does not yet support format based32hex. Therefore, it is not known whether padding ===== should be used.
    > But padding ===== is not used when specifying 'uuid_to_base32hex'.
    >
    >
    > > decode('06AJBM9TUTSVND36VA87V8BVJO', 'base32hex_to_uuid') -> 019535d9-3df7-79fb-b466-fa907fa17f9e
    >
    > > Suppose that the decode() takes text data at the first argument and
    > > returns UUID data, the function signature would be decode(text, text)
    > > -> uuid. But we cannot create two functions that have the same name
    > > and the same argument types.
    >
    > Yes, you're right. This is a problem that can't be solved without composite return values. We clearly took the wrong approach by coupling UUID conversion with encode/decode functions, which only apply to bytea. UUID and bytea are fundamentally different data types. Meanwhile, PostgreSQL has over 30 other type conversion functions that deal with other data types. For example, array_to_string, string_to_array, jsonb_to_record, to_char, to_timestamp, and to_hex. In this situation, the best solution would be to revert to the original uuid_to_base32hex() and base32hex_to_uuid() functions rather than deal with type incompatibility issues.
    >
    
    I think that type conversions and data encodings serve different
    purposes. Type conversions express semantic transformations between
    data types (e.g., text -> timestamp, jsonb -> record), while encodings
    are simply representations of binary data as text. For the latter,
    PostgreSQL already provides a well-defined abstraction through
    encode()/decode(). Mixing encoding logic with type-specific
    conversions would blur that boundary.
    
    Also, if we start adding dedicated functions for each supported
    encoding (uuid_to_base32hex, uuid_to_hex etc.), the number of
    functions could easily multiply. That’s exactly what encode() and
    decode() were designed to avoid.
    
    While I agree that base32hex should be the recommended, I'm really not
    sure it's a good design that PostgreSQL core should enforce it as the
    only built-in method. It seems better to me to provide flexible
    primitives, encode()/decode() plus UUID <-> bytea casts, and document
    base32hex as the canonical convention (if necessary). Or providing
    'uuid_encode(uuid, format text) -> text' and 'uuid_decode(text, format
    text) -> uuid' might make sense too, but I'm not sure. I'd like to
    hear opinions from other hackers too.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  14. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Andrey Borodin <x4mmm@yandex-team.ru> — 2025-10-25T18:07:10Z

    
    > On 25 Oct 2025, at 04:31, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > 
    > Or providing
    > 'uuid_encode(uuid, format text) -> text' and 'uuid_decode(text, format
    > text) -> uuid' might make sense too, but I'm not sure.
    
    I like the idea, so I drafted a prototype for discussion.
    Though I do not see what else methods should be provided along with added one...
    
    
    Best regards, Andrey Borodin.
    
  15. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-25T19:15:48Z

    > On 25 Oct 2025, at 04:31, Masahiko Sawada <sawada.mshk@gmail.com> wrote:> 
    > Or providing
    > 'uuid_encode(uuid, format text) -> text' and 'uuid_decode(text, format
    > text) -> uuid' might make sense too, but I'm not sure.
    > On Saturday 25 October 2025 at 09:07:39 pm GMT+3, Andrey Borodin <x4mmm@yandex-team.ru> wrote:
    > I like the idea, so I drafted a prototype for discussion.
    > Though I do not see what else methods should be provided along with added one...
    
    
    > Best regards, Andrey Borodin.
    
    If base32hex becomes the default string representation for UUIDs in PostgreSQL, then the canonical UUID string representation may be added into these functions for backward compatibility.
    Best regards,
    Sergey Prokhorenko
    
    
    
    
    
    
    
      
  16. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Aleksander Alekseev <aleksander@tigerdata.com> — 2025-10-27T10:23:27Z

    Hi,
    
    > > Or providing
    > > 'uuid_encode(uuid, format text) -> text' and 'uuid_decode(text, format
    > > text) -> uuid' might make sense too, but I'm not sure.
    >
    > I like the idea, so I drafted a prototype for discussion.
    > Though I do not see what else methods should be provided along with added one...
    
    I see no reason why we should forbid the use of base32 encoding with
    bytea. Or have different functions for this e.g. uuid_encode() and
    encode(). To me it looks like a poor API design.
    
    -- 
    Best regards,
    Aleksander Alekseev
    
    
    
    
  17. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-27T14:03:09Z

    Hi,
    > > Or providing
    > > 'uuid_encode(uuid, format text) -> text' and 'uuid_decode(text, format
    > > text) -> uuid' might make sense too, but I'm not sure.
    >
    > I like the idea, so I drafted a prototype for discussion.
    > Though I do not see what else methods should be provided along with added one...
    
    I see no reason why we should forbid the use of base32 encoding with
    bytea. Or have different functions for this e.g. uuid_encode() and
    encode(). To me it looks like a poor API design.
    
    -- 
    Best regards,
    Aleksander Alekseev
    
    ____________________________________________
    
    It seems that bytea is your personal interest, since you continue to impose your bytea when a better solution has already been found with uuid_encode() and uuid_decode().
    
    
    The bytea proposal has a lot of drawbacks:
    
    1. It requires unnecessary casting in addition to encoding/decoding. This complicates the interface and creates unnecessary cognitive load on developers. It also creates additional CPU load, although perhaps only a small amount.
    
    2. The encoding function encourages developers to use the slightly more compact base64 encoding (see https://www.postgresql.org/docs/current/functions-binarystring.html), which doesn't preserve sort order, isn't URL-safe, is case-sensitive, and requires specifying the case of letters when dictating. This also creates a serious problem of incompatibility between UUID encodings.
    
    3. The hashing functions used by bytea create a temptation to implement popular, idiotic ideas for hashing UUIDs to obscure their creation date and to hide internal keys from clients.
    
    4. Other various functions for bytea allow the construction of Frankenstein identifiers that compete with UUIDv7, which could negatively impact the reputation of UUIDs.
    
    The bytea type has nothing in common with the uuid type other than the binary encoding. Therefore, the bytea <-> uuid cast can only encourage abuse and errors, creating the illusion of unlimited developer power.
    
    
    The bytea proposal has no merit whatsoever. It's the worst, most insafe, and most harmful design, undermining efforts to widely adopt UUIDv7 and improve PostgreSQL.
    
    
    
      
  18. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Aleksander Alekseev <aleksander@tigerdata.com> — 2025-10-27T14:37:37Z

    Hi Sergey,
    
    > It seems that bytea is your personal interest, since you continue to impose your bytea when a better solution has already been found with uuid_encode() and uuid_decode().
    
    In the previous messages Masahiko Sawada wrote:
    
    > Or providing
    > 'uuid_encode(uuid, format text) -> text' and 'uuid_decode(text, format
    > text) -> uuid' might make sense too, but I'm not sure. I'd like to
    > hear opinions from other hackers too.
    
    I merely shared my personal opinion on why I think this is a bad idea.
    Let's see what other people think.
    
    -- 
    Best regards,
    Aleksander Alekseev
    
    
    
    
  19. Отв.: Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-27T15:33:31Z

    
    Hi Sergey,
    
    > It seems that bytea is your personal interest, since you continue to impose your bytea when a better solution has already been found with uuid_encode() and uuid_decode().
    
    In the previous messages Masahiko Sawada wrote:
    
    > Or providing
    > 'uuid_encode(uuid, format text) -> text' and 'uuid_decode(text, format
    > text) -> uuid' might make sense too, but I'm not sure. I'd like to
    > hear opinions from other hackers too.
    
    I merely shared my personal opinion on why I think this is a bad idea.
    Let's see what other people think.
    
    -- 
    Best regards,
    Aleksander Alekseev
    
    
    
    _____________________
    You didn't give any arguments in favor of your opinion
    
    
    
    
  20. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-27T20:09:43Z

    On Sat, Oct 25, 2025 at 11:07 AM Andrey Borodin <x4mmm@yandex-team.ru> wrote:
    >
    >
    >
    > > On 25 Oct 2025, at 04:31, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > Or providing
    > > 'uuid_encode(uuid, format text) -> text' and 'uuid_decode(text, format
    > > text) -> uuid' might make sense too, but I'm not sure.
    >
    > I like the idea, so I drafted a prototype for discussion.
    > Though I do not see what else methods should be provided along with added one...
    
    Thank you for drafting the patch! But I find it potentially confusing
    to have different encoding methods for bytea and UUID types. I don't
    see a compelling reason why the core should support base32hex
    exclusively for the UUID data type, nor why base32hex should be the
    only encoding method that the core provides for UUIDs (while we can
    use it by default).
    
    If we implement uuid_encode() and uuid_decode(), we might end up
    creating similar encoding and decoding functions for other data types
    as well, which doesn't seem like the best approach. I still believe
    that extending the existing encode() and decode() functions is a
    better starting point.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  21. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-27T22:36:51Z

     
     
     On Sat, Oct 25, 2025 at 11:07 AM Andrey Borodin <x4mmm@yandex-team.ru> wrote:
    >
    >
    >
    > > On 25 Oct 2025, at 04:31, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > Or providing
    > > 'uuid_encode(uuid, format text) -> text' and 'uuid_decode(text, format
    > > text) -> uuid' might make sense too, but I'm not sure.
    >
    > I like the idea, so I drafted a prototype for discussion.
    > Though I do not see what else methods should be provided along with added one...
    
    Thank you for drafting the patch! But I find it potentially confusing
    to have different encoding methods for bytea and UUID types. I don't
    see a compelling reason why the core should support base32hex
    exclusively for the UUID data type, nor why base32hex should be the
    only encoding method that the core provides for UUIDs (while we can
    use it by default).
    
    If we implement uuid_encode() and uuid_decode(), we might end up
    creating similar encoding and decoding functions for other data types
    as well, which doesn't seem like the best approach. I still believe
    that extending the existing encode() and decode() functions is a
    better starting point.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    ________________________________________________
     
    
    
    Masahiko,
     I wanted to highlight an important discussion among the authors and contributors of RFC 9562 regarding UUID text encoding:
    https://github.com/uuid6/new-uuid-encoding-techniques-ietf-draft/discussions/17#discussioncomment-10614817
     The RFC 9562 authors and contributors reached consensus that standardizing an alternate short text format for UUIDs is important. While the community debated between base32hex (RFC 4648) and Crockford's Base32, both were recognized for preserving lexicographical sort order, a critical property for database primary keys and URL-safe identifiers. Time constraints prevented inclusion in RFC 9562, but the discussion established that base32hex is the existing standard format already defined in RFC 4648, Section 7, specifically designed for sort-preserving encoding.
    
    This context is crucial because it underscores that the uuid type, as a first-class concept, deserves its own standardized text encoding.
    
    Regarding the proposal to couple UUID encoding with the bytea type through encode()/decode() functions: I understand the appeal of reusing existing infrastructure, but this creates a conceptual mismatch. UUID is a distinct semantic type in PostgreSQL, not merely binary data. The bytea type has existed for decades without base32hex encoding, and that's worked fine, because bytea represents arbitrary binary data, not universally unique identifiers with specific structural properties and needs.
    Consider PostgreSQL's own design philosophy. The documentation states:
    "9.5. Binary String Functions and Operators  This section describes functions and operators for examining and manipulating binary strings, that is values of type bytea. Many of these are equivalent, in purpose and syntax, to the text-string functions described in the previous section."
     PostgreSQL maintains parallel function sets for text strings and bytea precisely because they serve different purposes, despite the implementation overhead. The uuid type deserves the same treatment: it's not just another binary blob, but a type with specific semantics (uniqueness, version bits, variant encoding) and use cases (distributed identifiers, sortable keys, URL-safe representations).
    Why should uuid be treated as a second-class citizen and forced through bytea conversion, when text and bytea each have their own dedicated function families?
    You've been very careful in your previous arguments to separate data type conversion from encoding/decoding operations. I appreciate that rigor. However, the current proposal to route UUID encoding through bytea contradicts that principle. It merges two fundamentally different data types for convenience rather than correctness.
     If someone wants to add base32hex encoding/decoding to bytea for general binary data operations, that's a worthwhile but separate discussion. The uuid type, however, needs native base32hex support to fulfill its role as a first-class PostgreSQL type with a standardized compact text representation, as recommended by the RFC 9562 community.
    
    I would value your thoughts on these arguments.
    
    Best regards,
    Sergey Prokhorenko
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
      
  22. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Jelte Fennema-Nio <postgres@jeltef.nl> — 2025-10-28T09:30:04Z

    First of all, I'm definitely a proponent of being able to encode UUIDs
    using base32hex in Postgres.
    
    On Mon, 27 Oct 2025 at 23:37, Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    > I wanted to highlight an important discussion among the authors and contributors of RFC 9562 regarding UUID text encoding:
    >
    > https://github.com/uuid6/new-uuid-encoding-techniques-ietf-draft/discussions/17#discussioncomment-10614817
    
    I think a very important thing to note here is that this is a github
    discussion, not an officially accepted RFC. I think if it was an
    officially accepted RFC on how to encode UUIDs then you would have a
    lot less pushback here. Right now your emails mostly read like you
    want to push your preferential format, while essentially disallowing
    other encodings. While base32hex seems like a good choice for UUIDv7 I
    see no reason to give it preferential treatment at this point in time.
    crockford base32 seems just as valid. And e.g. base64url[1] seems
    totally fine for UUID versions that have no inherent ordering like
    UUIDv4. And if someone comes up with a base64urlhex format you could
    have even shorter bit still sortable UUIDs at the expense of
    legibility.
    
    The main reason why a specific encoding should receive preferential
    treatment in Postgres, would be if it was standardized, as that would
    help with interoperability. At this point in time there's no such
    standard (not even a draft), so forcing an explicit encoding will
    actually reduce interoperability, because people already encode their
    UUIDs in various different forms.
    
    > but the discussion established that base32hex is the existing standard format already defined in RFC 4648, Section 7, specifically designed for sort-preserving encoding.
    
    You even reach a similar conclusion here: not choosing crockford
    base32, purely because it does not have an official RFC.
    
    > This context is crucial because it underscores that the uuid type, as a first-class concept, deserves its own standardized text encoding.
    
    It already has! The standard text encoding is defined in RFC 4122.
    That's why postgres displays it as such when encoding to text.
    
    > Regarding the proposal to couple UUID encoding with the bytea type through encode()/decode() functions: I understand the appeal of reusing existing infrastructure, but this creates a conceptual mismatch. UUID is a distinct semantic type in PostgreSQL, not merely binary data. The bytea type has existed for decades without base32hex encoding, and that's worked fine, because bytea represents arbitrary binary data, not universally unique identifiers with specific structural properties and needs.
    
    I think by far the first step is to make the encoding of UUIDs in
    different formats possible in Postgres. The way to do so with the
    least API impact (and thus as you noticed, least pushback), would be
    to add base32hex to the list of encoding formats in the encode/decode
    functions. Then combining that with UUID <-> bytea casting (which also
    seems totally reasonable functionality to me), would give you the
    functionality (but not the defaults you want).
    
    In a follow up patch I would personally be fine making the API to
    encode UUIDs a bit more friendly. In particular, adding an overload to
    the encode function that takes a UUID instead of a bytea seems
    reasonable to me, i.e. encode(id uuid, format text) -> text
    
    I'm currently less convinced about a decode_uuid function though. I
    think some perf argument (including some benchmarks) would need to be
    made to convince me of its usefulness. Because purely from an API
    friendliness lens, I feel like decode('...', 'base32hex)::uuid and
    decode_uuid('...', 'base32hex') rank basically the same.
    
    Once/if an accepted RFC actually defines a default shorter encoding
    for UUIDs we could I would definitely be in favor of adding a
    decode_uuid function with the default encoding configured as a default
    argument. As well as adding the default argument to the uuid encode
    overload function.
    
    
    
    
  23. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> — 2025-10-28T11:53:51Z

    Jelte Fennema-Nio <postgres@jeltef.nl> writes:
    
    > First of all, I'm definitely a proponent of being able to encode UUIDs
    > using base32hex in Postgres.
    >
    > On Mon, 27 Oct 2025 at 23:37, Sergey Prokhorenko
    > <sergeyprokhorenko@yahoo.com.au> wrote:
    >>
    >> Regarding the proposal to couple UUID encoding with the bytea type
    >> through encode()/decode() functions: I understand the appeal of
    >> reusing existing infrastructure, but this creates a conceptual
    >> mismatch. UUID is a distinct semantic type in PostgreSQL, not merely
    >> binary data. The bytea type has existed for decades without base32hex
    >> encoding, and that's worked fine, because bytea represents arbitrary
    >> binary data, not universally unique identifiers with specific
    >> structural properties and needs.
    >
    > I think by far the first step is to make the encoding of UUIDs in
    > different formats possible in Postgres. The way to do so with the
    > least API impact (and thus as you noticed, least pushback), would be
    > to add base32hex to the list of encoding formats in the encode/decode
    > functions. Then combining that with UUID <-> bytea casting (which also
    > seems totally reasonable functionality to me), would give you the
    > functionality (but not the defaults you want).
    
    +1 for adding casts.
    
    > In a follow up patch I would personally be fine making the API to
    > encode UUIDs a bit more friendly. In particular, adding an overload to
    > the encode function that takes a UUID instead of a bytea seems
    > reasonable to me, i.e. encode(id uuid, format text) -> text
    
    Yeah, this works for encode, but not decode, since the argment types are
    the same (text, text) in both cases.
    
    > I'm currently less convinced about a decode_uuid function though. I
    > think some perf argument (including some benchmarks) would need to be
    > made to convince me of its usefulness. Because purely from an API
    > friendliness lens, I feel like decode('...', 'base32hex)::uuid and
    > decode_uuid('...', 'base32hex') rank basically the same.
    
    Agreed.
    
    > Once/if an accepted RFC actually defines a default shorter encoding
    > for UUIDs we could I would definitely be in favor of adding a
    > decode_uuid function with the default encoding configured as a default
    > argument. As well as adding the default argument to the uuid encode
    > overload function.
    
    If it's just one new form, do we need a separate decode function?  Could
    we not just make uuid_in() accept both forms (they're easily
    distinguishable by length), like bytea_in accepts both the old escape
    format and the new hex format?
    
    And if the new format becomes the standard and want to change the
    default output format, we would need a GUC like bytea_output anyway, to
    let users control when to make the change.
    
    - ilmari
    
    
    
    
  24. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Jelte Fennema-Nio <postgres@jeltef.nl> — 2025-10-28T12:24:49Z

    On Tue, 28 Oct 2025 at 12:53, Dagfinn Ilmari Mannsåker
    <ilmari@ilmari.org> wrote:
    > If it's just one new form, do we need a separate decode function?  Could
    > we not just make uuid_in() accept both forms (they're easily
    > distinguishable by length), like bytea_in accepts both the old escape
    > format and the new hex format?
    >
    > And if the new format becomes the standard and want to change the
    > default output format, we would need a GUC like bytea_output anyway, to
    > let users control when to make the change.
    
    Agreed to both of those. This seems too far out to spend much time
    discussing now.
    
    
    
    
  25. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-28T14:28:54Z

    First of all, I'm definitely a proponent of being able to encode UUIDsusing base32hex in Postgres.
    
    On Mon, 27 Oct 2025 at 23:37, Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    > I wanted to highlight an important discussion among the authors and contributors of RFC 9562 regarding UUID text encoding:
    >
    > https://github.com/uuid6/new-uuid-encoding-techniques-ietf-draft/discussions/17#discussioncomment-10614817
    
    I think a very important thing to note here is that this is a github
    discussion, not an officially accepted RFC. I think if it was an
    officially accepted RFC on how to encode UUIDs then you would have a
    lot less pushback here. Right now your emails mostly read like you
    want to push your preferential format, while essentially disallowing
    other encodings. While base32hex seems like a good choice for UUIDv7 I
    see no reason to give it preferential treatment at this point in time.
    crockford base32 seems just as valid. And e.g. base64url[1] seems
    totally fine for UUID versions that have no inherent ordering like
    UUIDv4. And if someone comes up with a base64urlhex format you could
    have even shorter bit still sortable UUIDs at the expense of
    legibility.
    
    The main reason why a specific encoding should receive preferential
    treatment in Postgres, would be if it was standardized, as that would
    help with interoperability. At this point in time there's no such
    standard (not even a draft), so forcing an explicit encoding will
    actually reduce interoperability, because people already encode their
    UUIDs in various different forms.
    
    > but the discussion established that base32hex is the existing standard format already defined in RFC 4648, Section 7, specifically designed for sort-preserving encoding.
    
    You even reach a similar conclusion here: not choosing crockford
    base32, purely because it does not have an official RFC.
    
    > This context is crucial because it underscores that the uuid type, as a first-class concept, deserves its own standardized text encoding.
    
    It already has! The standard text encoding is defined in RFC 4122.
    That's why postgres displays it as such when encoding to text.
    
    > Regarding the proposal to couple UUID encoding with the bytea type through encode()/decode() functions: I understand the appeal of reusing existing infrastructure, but this creates a conceptual mismatch. UUID is a distinct semantic type in PostgreSQL, not merely binary data. The bytea type has existed for decades without base32hex encoding, and that's worked fine, because bytea represents arbitrary binary data, not universally unique identifiers with specific structural properties and needs.
    
    I think by far the first step is to make the encoding of UUIDs in
    different formats possible in Postgres. The way to do so with the
    least API impact (and thus as you noticed, least pushback), would be
    to add base32hex to the list of encoding formats in the encode/decode
    functions. Then combining that with UUID <-> bytea casting (which also
    seems totally reasonable functionality to me), would give you the
    functionality (but not the defaults you want).
    
    In a follow up patch I would personally be fine making the API to
    encode UUIDs a bit more friendly. In particular, adding an overload to
    the encode function that takes a UUID instead of a bytea seems
    reasonable to me, i.e. encode(id uuid, format text) -> text
    
    I'm currently less convinced about a decode_uuid function though. I
    think some perf argument (including some benchmarks) would need to be
    made to convince me of its usefulness. Because purely from an API
    friendliness lens, I feel like decode('...', 'base32hex)::uuid and
    decode_uuid('...', 'base32hex') rank basically the same.
    
    Once/if an accepted RFC actually defines a default shorter encoding
    for UUIDs we could I would definitely be in favor of adding a
    decode_uuid function with the default encoding configured as a default
    argument. As well as adding the default argument to the uuid encode
    overload function.
    ______________________________________________________________________________________________
    
    
    Hi Jelte,
    I agree with your points.
    I believe we should put the discussion about compact UUID text encoding in PostgreSQL on hold for now. None of the proposed solutions has sufficient unconditional support from the participants. It makes sense to pause this discussion for more in-depth exploration to try and reach a consensus.
    Jelte, I particularly liked your idea of a new, dedicated, standardized encoding for UUIDs, base64urlhex, and dedicated encoding/decoding functions for this encoding in PostgreSQL. I will try to develop such an encoding and submit it for discussion. I suggest calling it base64uuid.
    My current attempt to establish base32hex as a de facto standard (even prior to an RFC) was unsuccessful. However, I remain convinced, like the authors of RFC 9562, that there should be only one standard compact encoding for UUIDs. Therefore, we must continue efforts to standardize such an encoding.
    As for Crockford's Base32, it was rejected because of a lack of support in standard programming language libraries. Otherwise, it's just as good as base32hex.
    
    Best regards,Sergey Prokhorenko
    
    
    
    
    
    
      
  26. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Jelte Fennema-Nio <postgres@jeltef.nl> — 2025-10-28T14:39:26Z

    On Tue, 28 Oct 2025 at 15:29, Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    > I believe we should put the discussion about compact UUID text encoding in PostgreSQL on hold for now.
    
    I agree with respect to the dedicated encode_uuid and decode_uuid functions.
    
    But I think having postgres support base32hex in encode/decode for
    bytea seems like a sensible thing in any case. As well as conversion
    between UUID and bytea. If someone wants to create patches for that,
    it seems like there'd be enough support for those to get them merged.
    
    
    
    
  27. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> — 2025-10-28T16:41:37Z

    Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> writes:
    
    > Jelte Fennema-Nio <postgres@jeltef.nl> writes:
    >
    >> Then combining that with UUID <-> bytea casting (which also
    >> seems totally reasonable functionality to me), would give you the
    >> functionality (but not the defaults you want).
    >
    > +1 for adding casts.
    
    Here's a patch for that.  I'm not 100% confident about the error code
    for invalid length, but that was the closest one I could find in
    errcodes.txt.
    
    I might do the base32hex encode/decode later, unless someone else beats
    me to it.
    
    - ilmari
    
    
  28. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-28T18:44:12Z

    On Tue, Oct 28, 2025 at 9:41 AM Dagfinn Ilmari Mannsåker
    <ilmari@ilmari.org> wrote:
    >
    > Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> writes:
    >
    > > Jelte Fennema-Nio <postgres@jeltef.nl> writes:
    > >
    > >> Then combining that with UUID <-> bytea casting (which also
    > >> seems totally reasonable functionality to me), would give you the
    > >> functionality (but not the defaults you want).
    > >
    > > +1 for adding casts.
    >
    > Here's a patch for that.  I'm not 100% confident about the error code
    > for invalid length, but that was the closest one I could find in
    > errcodes.txt.
    
    Thank you for the patch. I'll review it.
    
    > I might do the base32hex encode/decode later, unless someone else beats
    > me to it.
    
    Andrey has shared his patch for base32hex support before[1]. While it
    needs to be updated, it seems to implement sufficient function.
    
    Regards,
    
    [1] https://www.postgresql.org/message-id/6F76FA61-E2DC-44EF-9504-889D9BDB4EBD%40yandex-team.ru
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  29. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Sergey Prokhorenko <sergeyprokhorenko@yahoo.com.au> — 2025-10-28T21:56:32Z

    First of all, I'm definitely a proponent of being able to encode UUIDsusing base32hex in Postgres.
    
    On Mon, 27 Oct 2025 at 23:37, Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    > I wanted to highlight an important discussion among the authors and contributors of RFC 9562 regarding UUID text encoding:
    >
    > https://github.com/uuid6/new-uuid-encoding-techniques-ietf-draft/discussions/17#discussioncomment-10614817
    
    I think a very important thing to note here is that this is a github
    discussion, not an officially accepted RFC. I think if it was an
    officially accepted RFC on how to encode UUIDs then you would have a
    lot less pushback here. Right now your emails mostly read like you
    want to push your preferential format, while essentially disallowing
    other encodings. While base32hex seems like a good choice for UUIDv7 I
    see no reason to give it preferential treatment at this point in time.
    crockford base32 seems just as valid. And e.g. base64url[1] seems
    totally fine for UUID versions that have no inherent ordering like
    UUIDv4. And if someone comes up with a base64urlhex format you could
    have even shorter bit still sortable UUIDs at the expense of
    legibility.
    
    The main reason why a specific encoding should receive preferential
    treatment in Postgres, would be if it was standardized, as that would
    help with interoperability. At this point in time there's no such
    standard (not even a draft), so forcing an explicit encoding will
    actually reduce interoperability, because people already encode their
    UUIDs in various different forms.
    
    > but the discussion established that base32hex is the existing standard format already defined in RFC 4648, Section 7, specifically designed for sort-preserving encoding.
    
    You even reach a similar conclusion here: not choosing crockford
    base32, purely because it does not have an official RFC.
    
    > This context is crucial because it underscores that the uuid type, as a first-class concept, deserves its own standardized text encoding.
    
    It already has! The standard text encoding is defined in RFC 4122.
    That's why postgres displays it as such when encoding to text.
    
    > Regarding the proposal to couple UUID encoding with the bytea type through encode()/decode() functions: I understand the appeal of reusing existing infrastructure, but this creates a conceptual mismatch. UUID is a distinct semantic type in PostgreSQL, not merely binary data. The bytea type has existed for decades without base32hex encoding, and that's worked fine, because bytea represents arbitrary binary data, not universally unique identifiers with specific structural properties and needs.
    
    I think by far the first step is to make the encoding of UUIDs in
    different formats possible in Postgres. The way to do so with the
    least API impact (and thus as you noticed, least pushback), would be
    to add base32hex to the list of encoding formats in the encode/decode
    functions. Then combining that with UUID <-> bytea casting (which also
    seems totally reasonable functionality to me), would give you the
    functionality (but not the defaults you want).
    
    In a follow up patch I would personally be fine making the API to
    encode UUIDs a bit more friendly. In particular, adding an overload to
    the encode function that takes a UUID instead of a bytea seems
    reasonable to me, i.e. encode(id uuid, format text) -> text
    
    I'm currently less convinced about a decode_uuid function though. I
    think some perf argument (including some benchmarks) would need to be
    made to convince me of its usefulness. Because purely from an API
    friendliness lens, I feel like decode('...', 'base32hex)::uuid and
    decode_uuid('...', 'base32hex') rank basically the same.
    
    Once/if an accepted RFC actually defines a default shorter encoding
    for UUIDs we could I would definitely be in favor of adding a
    decode_uuid function with the default encoding configured as a default
    argument. As well as adding the default argument to the uuid encode
    overload function.
    
    ____________________________________________________
    
    
    Hi Jelte,
    
    Here's a project for a compact, sortable text encoding Base64UUID specifically for UUIDs, the idea for which you submitted ("base64urlhex"):
    https://github.com/sergeyprokhorenko/Base64UUID
    Where's the best place to discuss this: in this thread or starting a new one?
    
    Best regards,Sergey Prokhorenko
    
    
    
      
  30. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Jelte Fennema-Nio <postgres@jeltef.nl> — 2025-10-28T23:35:28Z

    On Tue, 28 Oct 2025 at 17:41, Dagfinn Ilmari Mannsåker
    <ilmari@ilmari.org> wrote:
    > Here's a patch for that.
    
    Looks good to me. Maybe add a test where not every byte is the same though.
    
    > I'm not 100% confident about the error code
    > for invalid length, but that was the closest one I could find in
    > errcodes.txt.
    
    The errorcode you chose seems acceptable to me, but I think a slightly
    more fitting option would be ERRCODE_INVALID_BINARY_REPRESENTATION.
    Error codes in postgres are pretty arbitrary though, so either seems
    fine to me.
    
    
    
    
  31. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Jelte Fennema-Nio <postgres@jeltef.nl> — 2025-10-28T23:44:00Z

    On Tue, 28 Oct 2025 at 22:58, Sergey Prokhorenko
    <sergeyprokhorenko@yahoo.com.au> wrote:
    > Where's the best place to discuss this: in this thread or starting a new one?
    
    I don't think core Postgres is the place where experimental encodings
    should be discussed and tried (it would fit great in an extension
    though). It sounds more like you should create an RFC or ask for
    feedback from some of the other contributors to the UUIDv7 RFC.
    
    
    
    
  32. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> — 2025-10-29T10:51:56Z

    Jelte Fennema-Nio <postgres@jeltef.nl> writes:
    
    > On Tue, 28 Oct 2025 at 17:41, Dagfinn Ilmari Mannsåker
    > <ilmari@ilmari.org> wrote:
    >> Here's a patch for that.
    >
    > Looks good to me. Maybe add a test where not every byte is the same though.
    
    Good point. I've replaced them with two randomly generated ones.
    
    >> I'm not 100% confident about the error code
    >> for invalid length, but that was the closest one I could find in
    >> errcodes.txt.
    >
    > The errorcode you chose seems acceptable to me, but I think a slightly
    > more fitting option would be ERRCODE_INVALID_BINARY_REPRESENTATION.
    > Error codes in postgres are pretty arbitrary though, so either seems
    > fine to me.
    
    That does seem like a better fit. It's used mainly in recv functions,
    which this basically is (but user-callable).
    
    Updated patch attaced.
    
    - ilmari
    
    
  33. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Aleksander Alekseev <aleksander@tigerdata.com> — 2025-10-29T11:31:29Z

    Hi,
    
    Thanks for the patch.
    
    > That does seem like a better fit. It's used mainly in recv functions,
    > which this basically is (but user-callable).
    >
    > Updated patch attaced.
    
    Perhaps bytea_uuid() should check the UUID format. Consider the
    following example:
    
    SELECT uuid_extract_version('\x019a2f859cedffffb99d9c55044a2563'::bytea::uuid);
     uuid_extract_version
    ----------------------
                       15
    
    There is no UUID version 15 according to RFC 9562, and the
    documentation for uuid_extract_version() says:
    
    """
    Extracts the version from a UUID of the variant described by RFC 9562.
    For other variants, this function returns null. For example, for a
    UUID generated by gen_random_uuid, this function will return 4.
    """
    
    If I read this correctly, either bytea_uuid() should reject this, or
    uuid_extract_version() should be modified to return NULL, or the
    documentation for uuid_extract_version() should be altered.
    
    -- 
    Best regards,
    Aleksander Alekseev
    
    
    
    
  34. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Aleksander Alekseev <aleksander@tigerdata.com> — 2025-10-29T11:57:59Z

    Hi,
    
    > > Updated patch attaced.
    >
    > Perhaps bytea_uuid() should check the UUID format. Consider the
    > following example:
    >
    > SELECT uuid_extract_version('\x019a2f859cedffffb99d9c55044a2563'::bytea::uuid);
    
    On the flip side we allow this:
    
    =# select '019a2f85-9ced-ffff-b99d-9c55044a2563' :: uuid;
                     uuid
    --------------------------------------
     019a2f85-9ced-ffff-b99d-9c55044a2563
    
    So I guess the patch is fine.
    
    -- 
    Best regards,
    Aleksander Alekseev
    
    
    
    
  35. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> — 2025-10-29T12:04:24Z

    Aleksander Alekseev <aleksander@tigerdata.com> writes:
    
    > Hi,
    >
    > Thanks for the patch.
    >
    >> That does seem like a better fit. It's used mainly in recv functions,
    >> which this basically is (but user-callable).
    >>
    >> Updated patch attaced.
    >
    > Perhaps bytea_uuid() should check the UUID format. Consider the
    > following example:
    >
    > SELECT uuid_extract_version('\x019a2f859cedffffb99d9c55044a2563'::bytea::uuid);
    >  uuid_extract_version
    > ----------------------
    >                    15
    
    The UUID input function doesn't do any such validation, so I don't see
    why the cast should behave any differently:
    
    # select '019a2f859cedffffb99d9c55044a2563'::uuid;
    ┌──────────────────────────────────────┐
    │                 uuid                 │
    ├──────────────────────────────────────┤
    │ 019a2f85-9ced-ffff-b99d-9c55044a2563 │
    └──────────────────────────────────────┘
    
    # select uuid_extract_version('019a2f859cedffffb99d9c55044a2563'::uuid);
    ┌──────────────────────┐
    │ uuid_extract_version │
    ├──────────────────────┤
    │                   15 │
    └──────────────────────┘
    (1 row)
    
    > There is no UUID version 15 according to RFC 9562, and the
    > documentation for uuid_extract_version() says:
    
    There's no version 15 specified _yet_.
    
    > """
    > Extracts the version from a UUID of the variant described by RFC 9562.
    > For other variants, this function returns null. For example, for a
    > UUID generated by gen_random_uuid, this function will return 4.
    > """
    >
    > If I read this correctly, either bytea_uuid() should reject this, or
    > uuid_extract_version() should be modified to return NULL, or the
    > documentation for uuid_extract_version() should be altered.
    
    Future RFCs could define new versions of this variant, which we should
    not reject or pretend don't have a version , just because we haven't
    heard of them yet.  In fact, RFC 9562 defines two new versions, v7 and
    v8, which by this argument PostgreSQL versions before 18 should reject.
    
    - ilmari
    
    
    
    
  36. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Andrey Borodin <x4mmm@yandex-team.ru> — 2025-10-29T12:19:08Z

    
    > On 28 Oct 2025, at 22:44, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > 
    > Andrey has shared his patch for base32hex support before[1]. While it
    > needs to be updated, it seems to implement sufficient function.
    
    I'd propose something like attached patch. It's on top of Ilmari's v2 patch with small suggestions as a step 2.
    
    Thanks!
    
    
    Best regards, Andrey Borodin.
    
    
  37. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-30T19:10:42Z

    On Wed, Oct 29, 2025 at 5:19 AM Andrey Borodin <x4mmm@yandex-team.ru> wrote:
    >
    >
    >
    > > On 28 Oct 2025, at 22:44, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > Andrey has shared his patch for base32hex support before[1]. While it
    > > needs to be updated, it seems to implement sufficient function.
    >
    > I'd propose something like attached patch. It's on top of Ilmari's v2 patch with small suggestions as a step 2.
    >
    
    I've reviewed the v3 patches, and here are some review comments.
    
    v3-0001 and v3-0002:
    
    -                               errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    -                               errmsg("invalid uuid length"));
    +                               (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    +                                errmsg("invalid length for UUID"),
    +                                errdetail("Expected %d bytes, got
    %d.", UUID_LEN, len)));
    
    How about the error message like "invalid input length for type uuid"?
    I think "uuid" should be lower case as it indicates PostgreSQL uuid
    data type, and it's better to use %s format instead of directly
    writing "uuid" (see string_to_uuid() for example).
    
    As for the errdetail message, should we add "bytea" also after "got %d"?
    
    ---
    +-- casts
    +SELECT '5b35380a-7143-4912-9b55-f322699c6770'::uuid::bytea;
    +SELECT '\x019a2f859ced7225b99d9c55044a2563'::bytea::uuid;
    +SELECT '\x1234567890abcdef'::bytea::uuid; -- error
    
    We already have tests for casting bytes to integer data types in
    strings.sql. I suggest moving the casting tests from bytea to uuid
    into therel. For the uuid.sql file, we could add a test to verify that
    a UUID value remains unchanged when it's cast to bytea and back to
    UUID. For example,
    
    SELECT v = v::bytea::uuid as matched FROM gen_random_uuid() v;
    
    ---
    I think we should update the documentation in the uuid section about
    casting data between bytea and uuid. For references, we have a similar
    description for bytea and integer[1].
    
    v3-0003:
    
    base32hex_encode() doesn't seem to add '=' paddings, but is it
    intentional? I don't see any description in RFC 4648 that we can omit
    '=' paddings.
    
    ---
    I think the patch should add tests not only for uuid data type but
    also for general cases like other encodings.
    
    ---
    In uuid.sql tests, how about adding some tests to check if base32hex
    maintains the sortability of UUIDv7 data?
    
    ---
    I would suggest registering the patches to the next commit fest if not yet.
    
    Regards,
    
    [1] https://www.postgresql.org/docs/devel/functions-binarystring.html
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  38. Re: Add uuid_to_base32hex() and base32hex_to_uuid() built-in functions

    Илья Чердаков <i.cherdakov.pg@gmail.com> — 2025-11-20T05:46:43Z

    31.10.2025 2:10, Masahiko Sawada wrote:
    > ---
    > I think we should update the documentation in the uuid section about
    > casting data between bytea and uuid. For references, we have a similar
    > description for bytea and integer[1].
    Greetings!
    I briefly tested the patched version of v3. The implemented
    functionality works correctly.
    
    ---
    You can also add a case with the error from v3-0002
    "invalid base32hex end sequence" to the tests :
    
    +        ereport(ERROR,
    +                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    +                 errmsg("invalid base32hex end sequence"),
    +                 errhint("Input data has non-zero padding bits.")));
    
    ---
    I agree with Masahiko Sawada; information about conversions
    should be added to the documentation.
    
    -- 
    Best regards,
    Ilya Cherdakov, PostgresPro