Skip to content

Conversation

@dantownsend
Copy link
Member

Resolves #1280

Comment on lines 50 to 51
# Supported?
return self.postgres
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cockroach doesn't have UUID 7 support yet (as far as I can see).

I guess we can just raise NotImplemented for now.

Comment on lines 11 to +26
def postgres(self):
return "uuid_generate_v4()"
"""
Historically we had to use `uuid_generate_v4()` from the `uuid-ossp`
extension.
Since Postgres 13 there is a built-in `gen_random_uuid` function which
generates UUID v4 values.
In Postgres 18, `uuidv4` was added, which is the same as
`gen_random_uuid`, but more precisely named. We will move to this at
some point in the future.
"""
return "gen_random_uuid()"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to split these changes out into a separate PR.

@sinisaos
Copy link
Member

@dantownsend Just one question. How would you solve this Postgres error without having to install some uuidv7 extension. Do you have another plan?

@dantownsend
Copy link
Member Author

@dantownsend Just one question. How would you solve this Postgres error without having to install some uuidv7 extension. Do you have another plan?

I was going to just put in the docs that it's Postgres 18 only for now.

I think there are some scripts out there somewhere which would allow us to use uuid 7 on older versions. If you can find one I'm not averse to using it (it might also solve the problem for CockroachDB too).

@sinisaos
Copy link
Member

I tried this custom function and by adding this function I was able to pass the tests. I don't know if this is the correct way to use it, but I added that custom function to postgres.py like this

if current_transaction:
    await current_transaction.connection.execute(
        """
        -- Source: https://gist.github.com/kjmph/5bd772b2c2df145aa645b837da7eca74
        create or replace function uuidv7()
        returns uuid
        as $$
        begin
        -- use random v4 uuid as starting point (which has the same variant we need)
        -- then overlay timestamp
        -- then set version 7 by flipping the 2 and 1 bit in the version 4 string
        return encode(
            set_bit(
            set_bit(
                overlay(uuid_send(gen_random_uuid())
                        placing substring(int8send(floor(extract(epoch from clock_timestamp()) * 1000)::bigint) from 3)
                        from 1 for 6
                ),
                52, 1
            ),
            53, 1
            ),
            'hex')::uuid;
        end
        $$
        language plpgsql
        volatile;
        """
    )
    response = await current_transaction.connection.fetch(ddl)

I also tried those changes in the app using id = UUID(primary_key=True, default=UUID7()) and it worked. UUID7 is generated correctly.

@dantownsend
Copy link
Member Author

I tried this custom function and by adding this function I was able to pass the tests. I don't know if this is the correct way to use it, but I added that custom function to postgres.py like this

if current_transaction:
    await current_transaction.connection.execute(
        """
        -- Source: https://gist.github.com/kjmph/5bd772b2c2df145aa645b837da7eca74
        create or replace function uuidv7()
        returns uuid
        as $$
        begin
        -- use random v4 uuid as starting point (which has the same variant we need)
        -- then overlay timestamp
        -- then set version 7 by flipping the 2 and 1 bit in the version 4 string
        return encode(
            set_bit(
            set_bit(
                overlay(uuid_send(gen_random_uuid())
                        placing substring(int8send(floor(extract(epoch from clock_timestamp()) * 1000)::bigint) from 3)
                        from 1 for 6
                ),
                52, 1
            ),
            53, 1
            ),
            'hex')::uuid;
        end
        $$
        language plpgsql
        volatile;
        """
    )
    response = await current_transaction.connection.fetch(ddl)

I also tried those changes in the app using id = UUID(primary_key=True, default=UUID7()) and it worked. UUID7 is generated correctly.

Thanks for this. I'm still a bit undecided how deep to go on this. Maybe we add this to the docs if people want to use UUID7 on older versions of Postgres.

@sinisaos
Copy link
Member

Here is another example of a custom Postgres uuid v7 function (from Piccolo issues). What I like about uuid v7 is they are sequential (similar to Serial column ). Cockroach does not work with uuid v7 in my case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UUID v7 support

3 participants