50 lines
1.5 KiB
PL/PgSQL
50 lines
1.5 KiB
PL/PgSQL
-- Migration: Create UUID v7 generation function
|
|
-- Description: PostgreSQL function to generate UUID v7 (time-ordered UUIDs)
|
|
-- Uses gen_random_uuid() as base, then overrides first 6 bytes with timestamp
|
|
|
|
-- Enable pgcrypto extension for gen_random_bytes()
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
-- Simple UUID v7 function that works with PostgreSQL's type system
|
|
CREATE OR REPLACE FUNCTION uuid_generate_v7()
|
|
RETURNS uuid AS $$
|
|
DECLARE
|
|
v_time double precision;
|
|
v_secs bigint;
|
|
v_msec int;
|
|
v_random bytea;
|
|
v_uuid bytea;
|
|
v_timestamp bytea;
|
|
BEGIN
|
|
-- Get current time
|
|
v_time := extract(epoch from clock_timestamp());
|
|
v_secs := floor(v_time);
|
|
v_msec := floor((v_time - v_secs) * 1000);
|
|
|
|
-- Generate random bytes for the rest
|
|
v_random := gen_random_bytes(10);
|
|
|
|
-- Build timestamp bytes (6 bytes = 48 bits)
|
|
v_timestamp := decode(lpad(to_hex(v_secs * 1000 + v_msec), 12, '0'), 'hex');
|
|
|
|
-- Combine: timestamp (6 bytes) + random (10 bytes)
|
|
v_uuid := v_timestamp || v_random;
|
|
|
|
-- Set version 7 (0111) in byte 6 (bits 4-7)
|
|
v_uuid := set_byte(v_uuid, 6, (get_byte(v_uuid, 6) & 15) | 112);
|
|
|
|
-- Set variant RFC 4122 (10xx) in byte 8
|
|
v_uuid := set_byte(v_uuid, 8, (get_byte(v_uuid, 8) & 63) | 128);
|
|
|
|
RETURN encode(v_uuid, 'hex')::uuid;
|
|
END;
|
|
$$ LANGUAGE plpgsql VOLATILE;
|
|
|
|
-- Comment
|
|
COMMENT ON FUNCTION uuid_generate_v7() IS 'Generates a UUID v7 (time-ordered) - RFC 9562 compliant';
|
|
|
|
-- Test the function
|
|
DO $$
|
|
BEGIN
|
|
RAISE NOTICE 'UUID v7 test: %', uuid_generate_v7();
|
|
END $$;
|