postgresql - 如何在postgresql数据库中对semver进行排序?

标签 postgresql sorting semantic-versioning

我在使用 PostrgreSQL 查询对 semversion 进行排序时遇到问题。

我发现了这样的主题:

https://dba.stackexchange.com/questions/74283/how-to-order-by-typical-software-release-versions-like-x-y-z

但他们只在 semversion 仅采用 MAJOR.MINOR.PATCH 形式时才讨论排序, 这确实很容易。但 semversion 可能还包括预发布版 (MAJOR.MINOR.PATCH-prerelase)。

引用自此处:https://semver.org/

Precedence for two pre-release versions with the same major, minor, and patch version MUST be determined by comparing each dot separated identifier from left to right until a difference is found as follows:

  1. Identifiers consisting of only digits are compared numerically.

  2. Identifiers with letters or hyphens are compared lexically in ASCII sort order.

  3. Numeric identifiers always have lower precedence than non-numeric identifiers.

  4. A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal.

Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.

对我来说困难的部分是创建“条件”排序,它可以考虑两种情况:

  • 当标识符仅包含数字时(应该进行数字比较)
  • 仅包含字母或连字符时(应使用 ASCII 排序顺序)

并采取相应措施以返回正确的订单。 我的表由两列组成:版本 (major.minor.patch) 和预发行版。

可以像版本列一样对预发行版进行排序 - 通过用“.”将其分割,并将每个段(标识符)视为字符串,但在某些情况下它不起作用。

示例:

如果我们考虑像这样的 semversion:

1.0.0-dev.123, 1.0.0-dev.124, 1.0.0-dev.1234

正确的顺序是:

1.0.0-dev.123, 1.0.0-dev.124, 1.0.0-dev.1234

而当我们将它们作为字符串进行比较时,输出将是:

1.0.0-dev.123, 1.0.0-dev.1234, 1.0.0-dev.124

谢谢!

最佳答案

我找到了解决方案。有时您无法使用库。 所以我们的想法是用零填充数字标识符,这样它们都包含相同数量的字符,然后像字符串一样对它们进行排序。

我的功能如下:

CREATE OR REPLACE FUNCTION numerical_identifier_pad (string text)
    RETURNS text AS
        '
        DECLARE
            result text;
        BEGIN
            IF string ~ ''^[0-9]{1,20}$'' THEN
                result :=  lpad(string, 20, ''0'');
            ELSE
                result := string;
            END IF;

            RETURN result;
        END;
        '
    LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION pad_numeric_identifiers_with_zeros (prerelease_column text)
    RETURNS text AS
        '
        DECLARE
            result text;
        BEGIN
            SELECT array_agg(a.numerical_identifier_pad)
                INTO result
                FROM (
                    SELECT numerical_identifier_pad(
                        unnest(string_to_array(prerelease_column, ''.'')::text[])
                    )
                ) AS a;

            RETURN result;
        END;
        '
    LANGUAGE plpgsql
    IMMUTABLE;

所以我所做的是在预发布专栏上使用 pad_numeric_identifiers_with_zeros 函数,然后对结果进行排序。

假设我们有预发行版,就像我第一篇文章中的示例一样。

  • dev.123
  • dev.124
  • dev.1234

pad_numeric_identifiers_with_zeros 会执行如下操作:

  • dev.0123
  • dev.0124
  • dev.1234

关于postgresql - 如何在postgresql数据库中对semver进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71798190/

相关文章:

sql - 完整性检查 : count(*) vs count(pkColumn)

java - 创建一个 SortedSet(对象)并向其插入元素或创建一个 ArrayList 并在之后对其进行排序是否更快?

PHP 按索引对二维数组进行排序(非关联)

kubernetes - 如何处理服务网格中的重大变化

frontend - 如何对前端项目进行版本控制?

sql - 允许在 postgreSQL 正则表达式文本中使用括号

postgresql - 为什么在 PostgreSQL 中创建空(无行,无列)表

spring - 如何使用 SSL 和 Spring Boot 连接到 PostgresQL?

c# - .NET Framework 的字符串比较中的错误

gradle - 在上游依赖项已更改时促进语义版本化的工件