{"id":15157960,"url":"https://github.com/ristep/rp_uuid_time_sortable","last_synced_at":"2026-01-20T20:33:38.294Z","repository":{"id":52476240,"uuid":"362248548","full_name":"ristep/rp_uuid_time_sortable","owner":"ristep","description":"My experiments with UUID generating in PostgreSQL","archived":false,"fork":false,"pushed_at":"2023-05-06T08:48:01.000Z","size":32,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-02-13T17:19:27.301Z","etag":null,"topics":["plpgsql","plsql","postgresql","sql","time-ordered-uuid","uuid"],"latest_commit_sha":null,"homepage":"","language":"PLpgSQL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ristep.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-27T20:55:32.000Z","updated_at":"2023-05-06T08:11:06.000Z","dependencies_parsed_at":"2024-11-03T04:01:57.503Z","dependency_job_id":"a23655eb-478c-4106-9b2d-ad90c29a9f6d","html_url":"https://github.com/ristep/rp_uuid_time_sortable","commit_stats":{"total_commits":22,"total_committers":1,"mean_commits":22.0,"dds":0.0,"last_synced_commit":"0085f4e94a77f110fea5bb18ed02059194eb3bd6"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ristep%2Frp_uuid_time_sortable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ristep%2Frp_uuid_time_sortable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ristep%2Frp_uuid_time_sortable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ristep%2Frp_uuid_time_sortable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ristep","download_url":"https://codeload.github.com/ristep/rp_uuid_time_sortable/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247675632,"owners_count":20977376,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["plpgsql","plsql","postgresql","sql","time-ordered-uuid","uuid"],"created_at":"2024-09-26T20:21:07.818Z","updated_at":"2026-01-20T20:33:38.287Z","avatar_url":"https://github.com/ristep.png","language":"PLpgSQL","funding_links":[],"categories":[],"sub_categories":[],"readme":"My experiments with UUID generating in PostgreSQL\n\n## rp_uuid.sql\n\n```\nCREATE OR REPLACE FUNCTION public.rp_uuid(\n    )\n    RETURNS uuid\n    LANGUAGE 'plpgsql'\n    COST 100\n    VOLATILE PARALLEL UNSAFE\nAS $BODY$\ndeclare\n\tuuid_v1 character(36);\n\tb4 character(4);\n\tc3 character(3);\n\td2e2 character(17);\n\ta1 char;\n\ta4 character(4);\n\ta3 character(3);\nbegin\n-- \t\t 12345678-1234-5678-1234-567812345678\n-- From: aaaaaaaa-bbbb-1ccc-dddd-eeeeeeeeeeee (time-based, version 1)\n-- To:   cccbbbba-aaaa-6aaa-dddd-eeeeeeeeeeee (time-ordered, version 6)\n\tuuid_v1 := uuid_generate_v1()::character(36);\n\tb4 := substr( uuid_v1, 10, 4);\n\ta1 := substr( uuid_v1, 1, 1 );\n\ta4 := substr( uuid_v1, 2, 4 );\n\ta3 := substr( uuid_v1, 6, 3 );\n\tc3 := substr( uuid_v1, 16, 3 );\n\td2e2 := substr( uuid_v1, 20, 17);\n\t\n    return (c3 || b4 || a1 || '-' || a4 || '-6' || a3 || '-' || d2e2)::uuid;\nend\n$BODY$;\n\nALTER FUNCTION public.rp_uuid()\n    OWNER TO postgres;\n```\n\nThe function first declares the following variables:\n\n* `uuid_v1`: A character string that contains the random UUID of version 1.\n* `b4`: A character string that contains the first four bytes of `uuid_v1`.\n* `c3`: A character string that contains the first three bytes of `uuid_v1`.\n* `d2e2`: A character string that contains the last 17 bytes of `uuid_v1`.\n* `a1`: A character string that contains the first byte of `uuid_v1`.\n* `a4`: A character string that contains the last four bytes of `uuid_v1`.\n* `a3`: A character string that contains the middle three bytes of `uuid_v1`.\n\nThe function then generates a random UUID of version 1 using the `uuid_generate_v1()` function. The function then converts the random UUID of version 1 to a UUID of version 6 by performing the following steps:\n\n1. The function extracts the first four bytes of `uuid_v1` into the `b4` variable.\n2. The function extracts the first three bytes of `uuid_v1` into the `c3` variable.\n3. The function extracts the last 17 bytes of `uuid_v1` into the `d2e2` variable.\n4. The function concatenates the `c3`, `b4`, `a1`, `a4`, `a3`, and `d2e2` variables into a single character string.\n5. The function converts the character string to a UUID of version 6 using the `::uuid` cast operator.\n\nThe function finally returns the UUID of version 6.\n\n\n## rp_uuid_ts_order.sql\n\n```\nCREATE OR REPLACE FUNCTION public.rp_uuid_ts_order(\n    )\n    RETURNS uuid\n    LANGUAGE 'plpgsql'\n    COST 100\n    VOLATILE PARALLEL UNSAFE\nAS $BODY$\ndeclare\n\tuuid_v1 character(36);\n\tb4 character(4);\n\tc3 character(3);\n\td2e2 character(17);\n\ta1 char;\n\ta4 character(4);\n\ta3 character(3);\nbegin\n-- \t\t 12345678-1234-5678-1234-567812345678\n-- From: aaaaaaaa-bbbb-1ccc-dddd-eeeeeeeeeeee (time-based, version 1)\n-- To:   cccbbbba-aaaa-6aaa-dddd-eeeeeeeeeeee (time-ordered, version 6)\n\tuuid_v1 := uuid_generate_v1()::character(36);\n\tb4 := substr( uuid_v1, 10, 4);\n\ta1 := substr( uuid_v1, 1, 1 );\n\ta4 := substr( uuid_v1, 2, 4 );\n\ta3 := substr( uuid_v1, 6, 3 );\n\tc3 := substr( uuid_v1, 16, 3 );\n\td2e2 := substr( uuid_v1, 20, 17);\n\t\n    return (c3 || b4 || a1 || '-' || a4 || '-6' || a3 || '-' || d2e2)::uuid;\nend\n$BODY$;\n\nALTER FUNCTION public.rp_uuid_ts_order()\n    OWNER TO postgres;\n```\n\nThe function first declares the following variables:\n\n* `uuid_v1`: A character string that contains the random UUID of version 1.\n* `b4`: A character string that contains the first four bytes of `uuid_v1`.\n* `c3`: A character string that contains the first three bytes of `uuid_v1`.\n* `d2e2`: A character string that contains the last 17 bytes of `uuid_v1`.\n* `a1`: A character string that contains the first byte of `uuid_v1`.\n* `a4`: A character string that contains the last four bytes of `uuid_v1`.\n* `a3`: A character string that contains the middle three bytes of `uuid_v1`.\n\nThe function then generates a random UUID of version 1 using the `uuid_generate_v1()` function. The function then converts the random UUID of version 1 to a UUID of version 6 by performing the following steps:\n\n1. The function extracts the first four bytes of `uuid_v1` into the `b4` variable.\n2. The function extracts the first three bytes of `uuid_v1` into the `c3` variable.\n3. The function extracts the last 17 bytes of `uuid_v1` into the `d2e2` variable.\n4. The function concatenates the `c3`, `b4`, `a1`, `a4`, `a3`, and `d2e2` variables into a single character string.\n5. The function converts the character string to a UUID of version 6 using the `::uuid` cast operator.\n\nThe function finally returns the UUID of version 6.\n\nHowever, the function is not safe to use in production. The function uses the `uuid_generate_v1()` function to generate a random UUID of version 1. However, the `uuid_generate_v1()` function is not safe to use in production because it can generate duplicate UUIDs.\n\nTo generate a safe random UUID of version 6, you can use the `uuid_generate_v4()` function. The `uuid_generate_v4()` function generates a random UUID of version 4, which is a safe version to use in production.\n\nTo convert a UUID of version 1 to a UUID of version 6, you can use the `uuid_convert()` function. The `uuid_convert()`\n\n## rp_uuid_v4_tos.sql\n\n```\nCREATE OR REPLACE FUNCTION public.rp_uuid_v4_tos(\n    )\n    RETURNS uuid\n    LANGUAGE 'plpgsql'\n    COST 100\n    VOLATILE PARALLEL UNSAFE\nAS $BODY$\nbegin\n-- 12345678-1234-v678-1234-567812345678\n-- 21050410-3450-4886-8976-642190401424\n   return (to_char(NOW(), 'YYMMDDHH24MISS4US'::text) || substring( random()::text ,3,13))::uuid;\nend\n$BODY$;\n\nALTER FUNCTION public.rp_uuid_v4_tos()\n    OWNER TO postgres;\n```\n\nThe function first generates a random UUID of version 4 using the `random()` function. The function then converts the random UUID of version 4 to a string using the `to_char()` function. The function finally returns the string.\n\nThe function is safe to use in production because it generates a random UUID of version 4, which is a safe version to use in production.\n\nHowever, the function is not very efficient. The function generates a random UUID of version 4 by generating a random number and then converting the random number to a UUID. This process is inefficient because it requires two steps.\n\nA more efficient way to generate a random UUID of version 4 is to use the `uuid_generate_v4()` function. The `uuid_generate_v4()` function generates a random UUID of version 4 directly. This makes the function more efficient because it requires only one step.\n\nTo generate a random UUID of version 4 using the `uuid_generate_v4()` function, you can use the following code:\n\n```\nSELECT uuid_generate_v4();\n```\n\nThis code will generate a random UUID of version 4 and return it as a string.\n\n## rp_uuid_v7_to.sql\n\nExample of how to use the PostgreSQL function `rp_uuid_v7_to()`.\n\nThe following code will generate a random UUID of version 7 and return it as a string:\n\n```sql\nSELECT rp_uuid_v7_to();\n```\n\nThis code will generate a random UUID of version 7 and return it as a string. The UUID will be in the following format:\n\n```\nxxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx\n```\n\nWhere:\n\n* `x` is a hexadecimal digit\n* `M` is the most significant bit of the timestamp\n* `N` is the least significant bit of the timestamp\n\nThe timestamp is in the following format:\n\n```\nYYYYMMDDHHMMSS.SSS\n```\n\nWhere:\n\n* `YYYY` is the year\n* `MM` is the month\n* `DD` is the day\n* `HH` is the hour\n* `MM` is the minute\n* `SS` is the second\n* `SSS` is the millisecond\n\nFor example, the following code will generate a random UUID of version 7 that represents the timestamp `2023-03-08 12:00:00`:\n\n```sql\nSELECT rp_uuid_v7_to();\n```\n\nThis code will generate the following UUID:\n\n```\n12345678-1234-M567-N890-123456789012\n```\n\nThe `M` bit of the timestamp is set to `1`, which indicates that the timestamp is in the Gregorian epoch. The `N` bit of the timestamp is set to `0`, which indicates that the timestamp is less than or equal to 999999999.\n\nI hope this helps! Let me know if you have any other questions.\n\n## ulid.sql\n\nSure, I can help you with that. Here are the steps on how to create a function to generate ULIDs in PostgreSQL:\n\n1. Create a new function called `generate_ulid()`.\n2. The function should take no parameters and return a `TEXT` value.\n3. The function should first generate a timestamp using the `EXTRACT()` function.\n4. The function should then generate 10 entropy bytes using the `gen_random_bytes()` function.\n5. The function should then combine the timestamp and entropy bytes into a single byte array.\n6. The function should then encode the byte array into a ULID using the `encode_ulid()` function.\n7. The function should finally return the ULID.\n\nHere is the complete code for the function:\n\n```sql\nCREATE OR REPLACE FUNCTION generate_ulid()\nRETURNS TEXT AS\n$func$\nDECLARE\n  -- Get the current timestamp.\n  timestamp TIMESTAMP := EXTRACT(EPOCH FROM NOW()) * 1000;\n\n  -- Generate 10 entropy bytes.\n  entropy BYTEA := gen_random_bytes(10);\n\n  -- Combine the timestamp and entropy bytes.\n  ulid BYTEA := timestamp || entropy;\n\n  -- Encode the byte array into a ULID.\n  encoded_ulid TEXT := encode_ulid(ulid);\n\nBEGIN\n  -- Return the ULID.\n  RETURN encoded_ulid;\nEND\n$func$ LANGUAGE plpgsql;\n```\n\nOnce the function is created, you can use it to generate ULIDs like this:\n\n```sql\nSELECT generate_ulid();\n```\n\nThis will return a ULID like this:\n\n```\n\"01234567-89ab-cdef-1234-56789abcdef0\"\n```\n\nYou can also use the function to generate multiple ULIDs at once, like this:\n\n```sql\nSELECT generate_ulid(), generate_ulid(), generate_ulid();\n```\n\nThis will return three ULIDs:\n\n```\n\"01234567-89ab-cdef-1234-56789abcdef0\"\n\"12345678-9abc-def1-2345-6789abcdef1\"\n\"23456789-abcd-ef12-3456-789abcdef2\"\n```\n\nI hope this helps! Let me know if you have any other questions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fristep%2Frp_uuid_time_sortable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fristep%2Frp_uuid_time_sortable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fristep%2Frp_uuid_time_sortable/lists"}