Skip to content

Instantly share code, notes, and snippets.

@Turbo87
Last active March 5, 2025 20:15
Show Gist options
  • Save Turbo87/f825b04d3e521ab37e85a51bef149bdb to your computer and use it in GitHub Desktop.
Save Turbo87/f825b04d3e521ab37e85a51bef149bdb to your computer and use it in GitHub Desktop.
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