postgresql 在postgres中比较软件版本

ss2ws0br  于 2023-03-12  发布在  PostgreSQL
关注(0)|答案(6)|浏览(179)

有没有办法在postgres中比较软件版本(例如X.Y.Z〉A.B. C)?我正在搜索string/varchar或“version”类型的函数。
我发现http://pgxn.org/dist/semver/doc/semver.html,但我正在寻找替代品(不那么容易部署..)
多谢了。

bnlyeluc

bnlyeluc1#

使用较便宜的**string_to_array()**。此处不需要昂贵的正则表达式:

SELECT string_to_array(v1, '.')::int[] AS v1
     , string_to_array(v2, '.')::int[] AS v2
     ,(string_to_array(v1, '.')::int[] > string_to_array(v2, '.')::int[]) AS cmp
FROM   versions;
  • db〈〉小提琴here*

老SQLF

xqk2d5yq

xqk2d5yq2#

您可以将版本拆分为数组,然后执行array comparison

select regexp_split_to_array(v1, '\.')::int[] v1, 
       regexp_split_to_array(v2, '\.')::int[] v2,
       regexp_split_to_array(v1, '\.')::int[] > regexp_split_to_array(v2, '\.')::int[] cmp
from versions;

演示

roqulrg3

roqulrg33#

如前所述,一个简单的方法是使用数字格式的版本。变量'server_version_num'包含数字格式的版本。
例如:

  • 版本9.5.2 =〉90502
  • 版本9.6.0 =〉90600
  • 版本10.5 =〉100500

选择当前设置(“服务器版本号”)
返回一个易于与其他版本号进行比较的数字。

w8biq8rn

w8biq8rn4#

更进一步Erwin's answer,我们可以创建一个函数来比较软件版本和需求(如in ruby)。我已经写了一个函数来做这个,使用它:

SELECT semver_match('4.2.0', '>= 4.0'); -- TRUE

下面是代码和测试:

CREATE OR REPLACE FUNCTION semver_match(version text, req text) RETURNS boolean
    LANGUAGE SQL
    IMMUTABLE
    RETURNS NULL ON NULL INPUT
    AS $$ 
    SELECT CASE
    WHEN req LIKE '~>%' THEN
        string_to_array(version, '.')::int[] >= string_to_array(substring(req from 4), '.')::int[]
        AND
        string_to_array(version, '.')::int[] <
        -- increment last item by one. (X.Y.Z => X.Y.(Z+1))
        array_append(
            (string_to_array(substring(req from 4), '.')::int[])[1:(array_length(string_to_array(req, '.'), 1) - 1)], -- X.Y
            (string_to_array(substring(req from 4), '.')::int[])[array_length(string_to_array(req, '.'), 1)] + 1 -- Z + 1
        )
 WHEN req LIKE '>=%' THEN string_to_array(version, '.')::int[] >= string_to_array(substring(req from 4), '.')::int[]
    WHEN req LIKE '<=%' THEN string_to_array(version, '.')::int[] <= string_to_array(substring(req from 4), '.')::int[]
    WHEN req LIKE '>%' THEN string_to_array(version, '.')::int[] > string_to_array(substring(req from 3), '.')::int[]
    WHEN req LIKE '<%' THEN string_to_array(version, '.')::int[] < string_to_array(substring(req from 3), '.')::int[]
   WHEN req LIKE '=%' THEN 
        (string_to_array(version, '.')::int[])[1:array_length(string_to_array(substring(req from 3), '.'), 1)] = 
        string_to_array(substring(req from 3), '.')::int[]
    ELSE NULL
    END $$;

-- tests.
SELECT 
    ver,
    req,
    CASE WHEN semver_match(ver, req) = expected
    THEN '✅' ELSE '❌' END AS test_passed
FROM (VALUES
    ('2.3', '>= 2.3', TRUE),
    ('2.3.1', '> 2.3', TRUE),
    ('2.3.1', '< 2.3.2', TRUE),
    ('2.3.1', '~> 2.3.2', FALSE),
    ('2.4.3', '~> 2.3.2', FALSE),
    ('2.3.2', '~> 2.3.2', TRUE),
    ('2.3.2', '= 2.3.2', TRUE),
    ('2.3.2', '= 2.3', TRUE),
    ('2.3.2', '= 2.4', FALSE)
) AS _ (ver, req, expected)

有关更多实现细节,请参见my blogpost on that topic

sauutmhj

sauutmhj5#

另一种方法是使用

SHOW server_version_num;

这将返回一个比较简单的版本号,例如90610对应9.6.10。

更新

根据下面的注解澄清此答案。此处生成的版本号是机器可读的。它被设计为唯一的,以避免冲突。
例如,Postgres版本12.1将生成120001,而12.10将生成120010,等等
https://database.guide/how-to-check-your-postgresql-version/

0vvn1miw

0vvn1miw6#

也许你可以添加一个pl函数,在我的例子中,我使用了python和distutils.version:

CREATE FUNCTION _is_major (a text, b text)
  RETURNS boolean
AS $$
    from distutils.version import LooseVersion 
    return LooseVersion(a) > LooseVersion(b)
$$ LANGUAGE PLPYTHONU;

您需要postgresql-plpython包。

相关问题