PG::UndefinedFunction: ERROR: function array_append(anyarray, anyelement) does not exist

PG::UndefinedFunction: ERROR: function array_append(anyarray, anyelement) does not exist

在我的应用程序中,我们很少有配置了 GitHub 工作流的测试用例,即使我确实只有 space 相关的文件更改,但仍然出现以下错误。不知道为什么我的规格仍然失败它之前工作正常。

An error occurred in a `before(:suite)` hook.
Failure/Error: ActiveMedian.create_function

ActiveRecord::StatementInvalid:
  PG::UndefinedFunction: ERROR:  function array_append(anyarray, anyelement) does not exist
  :       CREATE OR REPLACE FUNCTION median(anyarray)
           RETURNS float8 AS
        $$
          WITH q AS
          (
             SELECT val
             FROM unnest($***) val
             WHERE VAL IS NOT NULL
             ORDER BY ***
          ),
          cnt AS
          (
            SELECT COUNT(*) AS c FROM q
          )
          SELECT AVG(val)::float8
          FROM
          (
            SELECT val FROM q
            LIMIT  2 - MOD((SELECT c FROM cnt), 2)
            OFFSET GREATEST(CEIL((SELECT c FROM cnt) / 2.0) - ***,0)
          ) q2;
        $$
        LANGUAGE sql IMMUTABLE;

        DROP AGGREGATE IF EXISTS median(numeric);
        DROP AGGREGATE IF EXISTS median(double precision);
        DROP AGGREGATE IF EXISTS median(anyelement);
        CREATE AGGREGATE median(anyelement) (
          SFUNC=array_append,
          STYPE=anyarray,
          FINALFUNC=median,
          INITCOND='{}'
        );
# ./spec/rails_helper.rb:***54:in `seed'
# ./spec/rails_helper.rb:***:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---

# PG::UndefinedFunction:
#   ERROR:  function array_append(anyarray, anyelement) does not exist
#   ./spec/rails_helper.rb:***54:in `seed'

spec/rails_helper.rb 上有 ActiveMedian.create_function,这可能会导致问题。

如有任何线索或建议,我们将不胜感激

您使用的是 PostGreSQL 14,对吗?

因为对于 postgres 13 及之前的版本,这应该可以工作,请参阅 dbfiddle 中的测试结果。

我确认这不适用于 postgres 14,请参阅 dbfiddle 中的测试结果。

原因在PostGres 14 manual中解释:

User-defined objects that reference certain built-in array functions along with their argument types must be recreated (Tom Lane)

Specifically, array_append(), array_prepend(), array_cat(), array_position(), array_positions(), array_remove(), array_replace(), and width_bucket() used to take anyarray arguments but now take anycompatiblearray. Therefore, user-defined objects like aggregates and operators that reference those array function signatures must be dropped before upgrading, and recreated once the upgrade completes.

要使其正常工作,您可以改为:

CREATE OR REPLACE FUNCTION median(anycompatiblearray)
RETURNS float8 AS
$$
...
$$ LANGUAGE sql IMMUTABLE ;

...

CREATE AGGREGATE median(anycompatible) (
  SFUNC=array_append,
  STYPE=anycompatiblearray,
  FINALFUNC=median,
  INITCOND='{}'
);

经过一些研究,我通过如下更改 GitHub 上的 Postgres 图像版本解决了这个问题。

文件.github/workflows/build.yml

services:
      postgres:
        image: postgres:13
        ports:
          - 5432:5432

解决方案:这是Postgres 14版本的问题,为了快速解决降级到Postgres 13。