@@ -322,82 +322,82 @@ $body$ LANGUAGE plpgsql;
322322-- Bit allocation: 41 timestamp + 10 node + 12 sequence = 63 bits (keeps sign bit clear)
323323-- The sequence stores (elapsed_ms << 12) | sequence_within_ms, allowing
324324-- automatic reset of the sequence counter when the millisecond changes.
325- CREATE SEQUENCE IF NOT EXISTS pgdog .unique_id_seq ;
326-
327- CREATE OR REPLACE FUNCTION pgdog .unique_id(id_offset BIGINT DEFAULT 0 ) RETURNS BIGINT AS $body$
328- DECLARE
329- sequence_bits CONSTANT INTEGER := 12 ;
330- node_bits CONSTANT INTEGER := 10 ;
331- max_node_id CONSTANT INTEGER := (1 << node_bits) - 1 ; -- 1023
332- max_sequence CONSTANT INTEGER := (1 << sequence_bits) - 1 ; -- 4095
333- max_timestamp CONSTANT BIGINT := (1 ::bigint << 41 ) - 1 ;
334- pgdog_epoch CONSTANT BIGINT := 1764184395000 ; -- Wednesday, November 26, 2025 11:13:15 AM GMT-08:00
335- node_shift CONSTANT INTEGER := sequence_bits; -- 12
336- timestamp_shift CONSTANT INTEGER := sequence_bits + node_bits; -- 22
337-
338- node_id INTEGER ;
339- now_ms BIGINT ;
340- elapsed BIGINT ;
341- min_combined BIGINT ;
342- combined_seq BIGINT ;
343- seq INTEGER ;
344- timestamp_part BIGINT ;
345- node_part BIGINT ;
346- base_id BIGINT ;
347- BEGIN
348- -- Get node_id from pgdog.config.shard
349- SELECT pgdog .config .shard INTO node_id FROM pgdog .config ;
350-
351- IF node_id IS NULL THEN
352- RAISE EXCEPTION ' pgdog.config.shard not set' ;
353- END IF;
354-
355- IF node_id < 0 OR node_id > max_node_id THEN
356- RAISE EXCEPTION ' shard must be between 0 and %' , max_node_id;
357- END IF;
358-
359- LOOP
360- -- Get next combined sequence value
361- combined_seq := nextval(' pgdog.unique_id_seq' );
362-
363- -- Get current time in milliseconds since Unix epoch
364- now_ms := (EXTRACT(EPOCH FROM clock_timestamp()) * 1000 )::bigint ;
365- elapsed := now_ms - pgdog_epoch;
366-
367- IF elapsed < 0 THEN
368- RAISE EXCEPTION ' Clock is before PgDog epoch (November 26, 2025)' ;
369- END IF;
370-
371- -- Minimum valid combined value for current millisecond
372- min_combined := elapsed << 12 ;
373-
374- -- If sequence is at or ahead of current time, we're good
375- IF combined_seq >= min_combined THEN
376- EXIT;
377- END IF;
378-
379- -- Sequence is behind current time, advance it
380- PERFORM setval(' pgdog.unique_id_seq' , min_combined, false);
381- END LOOP;
382-
383- -- Decompose the combined sequence value
384- seq := (combined_seq & max_sequence)::integer ;
385- elapsed := combined_seq >> 12 ;
386-
387- IF elapsed > max_timestamp THEN
388- RAISE EXCEPTION ' Timestamp overflow: % > %' , elapsed, max_timestamp;
389- END IF;
390-
391- -- Compose the ID: timestamp | node | sequence
392- timestamp_part := elapsed << timestamp_shift;
393- node_part := node_id::bigint << node_shift;
394- base_id := timestamp_part | node_part | seq;
395-
396- RETURN base_id + id_offset;
397- END;
398- $body$ LANGUAGE plpgsql;
399-
400- GRANT USAGE ON SEQUENCE pgdog .unique_id_seq TO PUBLIC;
401-
402- -- Allow functions to be executed by anyone.
403- GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA pgdog TO PUBLIC;
325+ -- CREATE SEQUENCE IF NOT EXISTS pgdog.unique_id_seq;
326+
327+ -- CREATE OR REPLACE FUNCTION pgdog.unique_id(id_offset BIGINT DEFAULT 0) RETURNS BIGINT AS $body$
328+ -- DECLARE
329+ -- sequence_bits CONSTANT INTEGER := 12;
330+ -- node_bits CONSTANT INTEGER := 10;
331+ -- max_node_id CONSTANT INTEGER := (1 << node_bits) - 1; -- 1023
332+ -- max_sequence CONSTANT INTEGER := (1 << sequence_bits) - 1; -- 4095
333+ -- max_timestamp CONSTANT BIGINT := (1::bigint << 41) - 1;
334+ -- pgdog_epoch CONSTANT BIGINT := 1764184395000; -- Wednesday, November 26, 2025 11:13:15 AM GMT-08:00
335+ -- node_shift CONSTANT INTEGER := sequence_bits; -- 12
336+ -- timestamp_shift CONSTANT INTEGER := sequence_bits + node_bits; -- 22
337+
338+ -- node_id INTEGER;
339+ -- now_ms BIGINT;
340+ -- elapsed BIGINT;
341+ -- min_combined BIGINT;
342+ -- combined_seq BIGINT;
343+ -- seq INTEGER;
344+ -- timestamp_part BIGINT;
345+ -- node_part BIGINT;
346+ -- base_id BIGINT;
347+ -- BEGIN
348+ -- -- Get node_id from pgdog.config.shard
349+ -- SELECT pgdog.config.shard INTO node_id FROM pgdog.config;
350+
351+ -- IF node_id IS NULL THEN
352+ -- RAISE EXCEPTION 'pgdog.config.shard not set';
353+ -- END IF;
354+
355+ -- IF node_id < 0 OR node_id > max_node_id THEN
356+ -- RAISE EXCEPTION 'shard must be between 0 and %', max_node_id;
357+ -- END IF;
358+
359+ -- LOOP
360+ -- -- Get next combined sequence value
361+ -- combined_seq := nextval('pgdog.unique_id_seq');
362+
363+ -- -- Get current time in milliseconds since Unix epoch
364+ -- now_ms := (EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::bigint;
365+ -- elapsed := now_ms - pgdog_epoch;
366+
367+ -- IF elapsed < 0 THEN
368+ -- RAISE EXCEPTION 'Clock is before PgDog epoch (November 26, 2025)';
369+ -- END IF;
370+
371+ -- -- Minimum valid combined value for current millisecond
372+ -- min_combined := elapsed << 12;
373+
374+ -- -- If sequence is at or ahead of current time, we're good
375+ -- IF combined_seq >= min_combined THEN
376+ -- EXIT;
377+ -- END IF;
378+
379+ -- -- Sequence is behind current time, advance it
380+ -- PERFORM setval('pgdog.unique_id_seq', min_combined, false);
381+ -- END LOOP;
382+
383+ -- -- Decompose the combined sequence value
384+ -- seq := (combined_seq & max_sequence)::integer;
385+ -- elapsed := combined_seq >> 12;
386+
387+ -- IF elapsed > max_timestamp THEN
388+ -- RAISE EXCEPTION 'Timestamp overflow: % > %', elapsed, max_timestamp;
389+ -- END IF;
390+
391+ -- -- Compose the ID: timestamp | node | sequence
392+ -- timestamp_part := elapsed << timestamp_shift;
393+ -- node_part := node_id::bigint << node_shift;
394+ -- base_id := timestamp_part | node_part | seq;
395+
396+ -- RETURN base_id + id_offset;
397+ -- END;
398+ -- $body$ LANGUAGE plpgsql;
399+
400+ -- GRANT USAGE ON SEQUENCE pgdog.unique_id_seq TO PUBLIC;
401+
402+ -- -- Allow functions to be executed by anyone.
403+ -- GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA pgdog TO PUBLIC;
0 commit comments