postgresql 扩展多维数据集出现pg_dump / pg_restore错误

fcipmucu  于 2022-12-26  发布在  PostgreSQL
关注(0)|答案(3)|浏览(304)

我在转储和恢复一个数据库时遇到了一个问题,我想是因为公共模式中的一些扩展。抛出错误的扩展似乎是Cube扩展或EarthDistance扩展。这是我得到的错误:

pg_restore: [archiver (db)] Error from TOC entry 2983;
pg_restore: [archiver (db)] could not execute query: ERROR: type "earth" does not exist
LINE 1: ...ians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth

QUERY: SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth
CONTEXT: SQL function "ll_to_earth" during inlining
   Command was: REFRESH MATERIALIZED VIEW public.locationsearch

我自己写的一些函数也有类似的问题,最后是搜索路径,所以显式地将这些函数的搜索路径设置为public解决了我的问题。我尝试了ll_to_earth,但似乎整个扩展都有问题。我真的不想尝试安装pg_catalog的扩展,因为这似乎是一个糟糕的做法。
这是我的典型转储命令:
pg_dump -U postgres -h ipAddress -p 5432 -w -F t database > database.tar
接着是:
pg_restore -U postgres -h localhost -p 5432 -w -d postgres -C "database.tar"
包含数据的完全转储大约为4gb,但我尝试仅转储包含-s-F p的模式,有趣的是,这只是开始:

--
-- PostgreSQL database dump
--

-- Dumped from database version 12.2
-- Dumped by pg_dump version 12.2

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;

--
-- Name: cube; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS cube WITH SCHEMA public;

--
-- Name: EXTENSION cube; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION cube IS 'data type for multidimensional cubes';

--
-- Name: earthdistance; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS earthdistance WITH SCHEMA public;

--
-- Name: EXTENSION earthdistance; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION earthdistance IS 'calculate great-circle distances on the surface of the Earth';

我想我有点困惑了......从逻辑上讲,这与我使用tar格式的情况不一样吗?我知道问题是,当pg_restore到达该物化视图并尝试使用函数ll_to_earth(float8, float8)时,它会失败,因为该函数不在其搜索路径中或尚未恢复。但这不就意味着分机是第一个要恢复的吗?这个问题能解决吗?
这是我编写的脚本的一部分,该脚本将在生产环境中转储数据库,并每天在测试环境中恢复数据库,以使它们匹配。在我开始使用此扩展之前,它工作了几个月,我不知道如何纠正它。

6jygbczu

6jygbczu1#

出于安全原因,pg_dumpsearch_path设置为空,因此如果在没有模式限定的情况下引用系统模式pg_catalog中的对象,则只会找到这些对象。
现在您的SQL函数使用没有模式的数据类型earth(可能是public),所以您得到了错误消息。
您必须更改函数以使用像public.earth这样的限定名作为扩展对象。或者,可能更好的方法是修复函数的search_path

ALTER FUNCTION myfun SET search_path = public;

无论如何,这是一个好主意,因为如果用户修改search_path,函数将停止工作,根据函数的定义或使用方式,这甚至可能构成安全问题(这就是pg_dump这样做的原因)。

tv6aics1

tv6aics12#

我在这个answer中找到了一种方法,我在pg_catalog方案中创建扩展,正如文档所述,* 总是搜索路径的有效部分 *。

CREATE EXTENSION IF NOT EXISTS cube SCHEMA pg_catalog; 
CREATE EXTENSION IF NOT EXISTS earthdistance SCHEMA pg_catalog;

人们认为这是一个糟糕的做法,因为它可能会污染系统目录等,但它在我的用例中很好地为我服务-现在我可以pg_dump/pg_restore没有后顾之忧。
注意:我发现这个线程包含一个earthdistance扩展补丁。很遗憾,它还没有被合并。

ykejflvf

ykejflvf3#

有同样的问题,但是上面的解决方案不起作用。在数据插入过程中,我得到了以下错误

ERROR: type "earth" does not exist
LINE 1: ...ians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth

QUERY: SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth
CONTEXT: SQL function "ll_to_earth" during inlining

在pgdump文件中,我必须替换以下行(在文件的顶部)

SELECT pg_catalog.set_config('search_path', '', false);

SELECT pg_catalog.set_config('search_path', 'public', false);

相关问题