-
Notifications
You must be signed in to change notification settings - Fork 19
Open
Description
I wrote the following, heavily inspired by what you already wrote:
CREATE FUNCTION public.generate_ulid() RETURNS uuid
LANGUAGE plpgsql
AS $$
DECLARE
timestamp BYTEA = E'\\000\\000\\000\\000\\000\\000';
unix_time BIGINT;
BEGIN
unix_time = (EXTRACT(EPOCH FROM NOW()) * 1000)::BIGINT;
timestamp = SET_BYTE(timestamp, 3, (unix_time >> 40)::BIT(8)::INTEGER);
timestamp = SET_BYTE(timestamp, 2, (unix_time >> 32)::BIT(8)::INTEGER);
timestamp = SET_BYTE(timestamp, 1, (unix_time >> 24)::BIT(8)::INTEGER);
timestamp = SET_BYTE(timestamp, 0, (unix_time >> 16)::BIT(8)::INTEGER);
timestamp = SET_BYTE(timestamp, 5, (unix_time >> 8)::BIT(8)::INTEGER);
timestamp = SET_BYTE(timestamp, 4, unix_time::BIT(8)::INTEGER);
RETURN CAST(substring(CAST((timestamp || gen_random_bytes(10)) AS text) from 3) AS uuid);
END
$$;
It generates a ULID, but in the UUID format. The order of the bytes is a bit unintuitive due to the UUID format/endianness.
This function makes it easier to use the uuid
PostGres type to hold ULIDs. This makes for smaller, faster indexes (c.f. indexing on text
).
kdevan, KyleKing and docteurklein
Metadata
Metadata
Assignees
Labels
No labels