Last active
March 5, 2025 20:15
-
-
Save Turbo87/f825b04d3e521ab37e85a51bef149bdb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE OR REPLACE FUNCTION semver_ord(num varchar) RETURNS jsonb AS $$ | |
DECLARE | |
max_prerelease_parts constant int := 30; | |
match_result text[] := regexp_match(num, '^(\d+).(\d+).(\d+)(?:-([0-9A-Za-z\-.]+))?'); | |
prerelease jsonb; | |
prerelease_part text; | |
i int := 0; | |
BEGIN | |
IF match_result[4] IS NULL THEN | |
-- A JSONB object has higher precedence than an array and versions without | |
-- prerelease specifiers should have higher precedence too | |
prerelease := json_build_object(); | |
ELSE | |
-- Fill `prerelease` array with `null` values. | |
-- Shorter arrays have lower precedence in JSONB, so we must | |
-- ensure that they have the same length | |
prerelease := to_jsonb(array_fill(NULL::bool, ARRAY[max_prerelease_parts])); | |
-- Split prerelease string by `.` and append items to `prerelease` array | |
FOREACH prerelease_part IN ARRAY string_to_array(match_result[4], '.') | |
LOOP | |
-- Parse parts as numbers if they consist of only digits | |
IF regexp_like(prerelease_part, '^\d+$') THEN | |
-- In JSONB a number has higher precedence than a string | |
-- but in semver it is the other way around, so we use true/false | |
-- to work around this. | |
prerelease := jsonb_set(prerelease, array[i::text], to_jsonb(false)); | |
prerelease := jsonb_set(prerelease, array[(i + 1)::text], to_jsonb(prerelease_part::numeric)); | |
ELSE | |
prerelease := jsonb_set(prerelease, array[i::text], to_jsonb(true)); | |
prerelease := jsonb_set(prerelease, array[(i + 1)::text], to_jsonb(prerelease_part)); | |
END IF; | |
i := i + 2; | |
EXIT WHEN i > max_prerelease_parts; | |
END LOOP; | |
END IF; | |
RETURN json_build_array( | |
match_result[1]::numeric, | |
match_result[2]::numeric, | |
match_result[3]::numeric, | |
prerelease | |
); | |
END; | |
$$ LANGUAGE plpgsql IMMUTABLE; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment