Skip to content

Instantly share code, notes, and snippets.

@pabloogc
Last active May 9, 2022 19:40
Show Gist options
  • Save pabloogc/b6494477bfa14ae90a045d15aa0ff780 to your computer and use it in GitHub Desktop.
Save pabloogc/b6494477bfa14ae90a045d15aa0ff780 to your computer and use it in GitHub Desktop.
Function for generating uuid v7 on Postgres as defined in the RFC https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format#section-5.2
export function uuid7(): UUID {
// Simple implementation using built in gen_random_uuid()
// gen_random_uuid(): '4047541d-a7bf-4d8a-87c2-585cab7ef52e'
// strip random head and version: '_______________d8a-87c2-585cab7ef52e'
// concatenate epoch and version 7: 'xxxxxxxx-xxxx-7d8a-87c2-585cab7ef52e
const v4 = uuid.v4().slice(8 + 4 + 2 + 1, 36);
const date = Date.now().toString(16).padStart(12, '0');
return date.slice(0, 8) + '-' + date.slice(8, 8 + 5) + '-7' + v4;
}
create extension if not exists "uuid-ossp";
-- SPEC: https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format#section-5.2
-- 0 1 2 3
-- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- | unix_ts_ms |
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- | unix_ts_ms | ver | rand_a |
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- |var| rand_b |
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- | rand_b |
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
create or replace function uuid_generate_v7() returns uuid as
$$
declare
random_uuid_tail varchar(21) := null;
epoch_hex varchar(12) := null;
begin
-- Simple implementation using built in gen_random_uuid()
-- uuid_generate_v4(): '4047541d-a7bf-4d8a-87c2-585cab7ef52e'
-- strip random head and version: '_______________d8a-87c2-585cab7ef52e'
-- concatenate epoch and version 7: 'xxxxxxxx-xxxx-7d8a-87c2-585cab7ef52e
random_uuid_tail := substr(uuid_generate_v4()::varchar(36), 16);
epoch_hex := lpad(to_hex((extract(epoch from clock_timestamp()) * 1000)::bigint), 12, '0');
return (substr(epoch_hex, 0, 9) || '-' || substr(epoch_hex, 9, 5) || '-7' || random_uuid_tail)::uuid;
end
$$ language plpgsql;
-- select uuid_generate_v7() as uuid,
-- extract(MICROSECOND from clock_timestamp() - statement_timestamp()) time;
-- EXAMPLE OUTPUT:
--
-- |uuid |time |
-- |--------------------------------------|------------------|
-- |0180a385-5edf-7e93-8e4f-cf923219f7d2 |195 |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment