-- Migration: Create UUID v7 generation function -- Description: PostgreSQL function to generate UUID v7 (time-ordered UUIDs) -- UUID v7 format: tttttttt-tttt-7xxx-yxxx-xxxxxxxxxxxx -- Where: t = timestamp, 7 = version, y = variant, x = random -- Enable pgcrypto extension for gen_random_bytes() CREATE EXTENSION IF NOT EXISTS pgcrypto; -- Create or replace the uuid_generate_v7 function CREATE OR REPLACE FUNCTION uuid_generate_v7() RETURNS uuid AS $$ DECLARE unix_ts_ms bigint; uuid_bytes bytea; BEGIN -- Get current Unix timestamp in milliseconds unix_ts_ms := (EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::bigint; -- Build the UUID bytes: -- First 6 bytes: timestamp (48 bits) -- Next 2 bytes: version (4 bits) + random (12 bits) -- Last 8 bytes: variant (2 bits) + random (62 bits) uuid_bytes := set_byte( set_byte( set_byte( set_byte( set_byte( set_byte( gen_random_bytes(16), 0, (unix_ts_ms >> 40)::int ), 1, (unix_ts_ms >> 32)::int ), 2, (unix_ts_ms >> 24)::int ), 3, (unix_ts_ms >> 16)::int ), 4, (unix_ts_ms >> 8)::int ), 5, unix_ts_ms::int ); -- Set version 7 (0111) in byte 6 uuid_bytes := set_byte(uuid_bytes, 6, (get_byte(uuid_bytes, 6) & 15) | 112); -- Set variant RFC 4122 (10xx) in byte 8 uuid_bytes := set_byte(uuid_bytes, 8, (get_byte(uuid_bytes, 8) & 63) | 128); RETURN encode(uuid_bytes, '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 $$;