File: util_uuid7_time.sql

package info (click to toggle)
pg-partman 5.3.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 9,952 kB
  • sloc: sql: 153,740; ansic: 368; python: 361; makefile: 36; sh: 20
file content (43 lines) | stat: -rw-r--r-- 1,303 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
 * Convenience helper functions to support time based partitioning for UUIDv7 columns.
 * Set the following functions as p_time_encoder, p_time_decoder params for time based
 * partitioning of UUIDv7 columns
 */

CREATE FUNCTION @extschema@.uuid7_time_encoder(ts TIMESTAMPTZ)
RETURNS UUID
LANGUAGE plpgsql
AS $$
DECLARE
    ts_millis BIGINT;
    ts_hex TEXT;
BEGIN
    -- Convert the milliseconds to a 12 char hex with zero pad
    ts_millis := EXTRACT(EPOCH FROM ts) * 1000;
    ts_hex := lpad(to_hex(ts_millis), 12, '0');

    -- Split the timestamp into two parts as per spec
    RETURN substr(ts_hex, 1, 8) || '-' || substr(ts_hex, 9, 4) || '-0000-0000-000000000000';
END;
$$;


-- Currently time decoder function must take a text parameter. See if this can be more flexible in the future
CREATE FUNCTION @extschema@.uuid7_time_decoder(uuidv7 TEXT)
RETURNS TIMESTAMPTZ
LANGUAGE plpgsql
AS $$
DECLARE
    ts_hex TEXT;
    ts_millis BIGINT;
    extracted_ts TIMESTAMPTZ;
BEGIN
    -- Extract the first 12 characters of the UUID which represent the timestamp
    ts_hex := substr(uuidv7::TEXT, 1, 8) || substr(uuidv7::TEXT, 10, 4);

    -- Convert the hex timestamp to a BIGINT (milliseconds)
    ts_millis := ('x' || ts_hex)::BIT(48)::BIGINT;

    RETURN to_timestamp(ts_millis / 1000.0);
END;
$$;