简体   繁体   English

pg_dump / pg_restore 扩展立方体错误

[英]pg_dump / pg_restore error with extension cube

I've been running into an issue dumping and restoring one of my databases I think because of some extensions in the public schema.由于公共模式中的一些扩展,我一直在转储和恢复我的一个数据库时遇到问题。 The extension that's throwing the error seems to be the Cube extension or the EarthDistance extension.引发错误的扩展似乎是Cube扩展或EarthDistance扩展。 This is the error I'm getting:这是我得到的错误:

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

I was having a similarly different issue with some functions that I had written myself and the issue ended up being the search path, so explicitly setting the search path for those functions to public solved my issue.我自己编写的一些函数遇到了类似的不同问题,问题最终是搜索路径,因此明确地将这些函数的搜索路径设置为公共解决了我的问题。 I tried the same with ll_to_earth but it seems the entire extension is the problem.我对ll_to_earth进行了同样的尝试,但似乎整个扩展都是问题所在。 I don't really want to try and install an extension to pg_catalog because that seems like poor practice.我真的不想尝试安装pg_catalog的扩展,因为这似乎是不好的做法。

This is my typical dump command:这是我的典型转储命令:

pg_dump -U postgres -h ipAddress -p 5432 -w -F t database > database.tar

Followed by:其次是:

pg_restore -U postgres -h localhost -p 5432 -w -d postgres -C "database.tar"

The full dump with data is about 4gb, but I tried dumping just the schema with -s and -F p and interestingly this is the beginning:包含数据的完整转储约为 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';

I guess I'm confused by...logically, isn't this the same as it would be if I'd used the tar format?我想我对...感到困惑……从逻辑上讲,这与我使用 tar 格式时的情况不一样吗? I know the issue is that when pg_restore gets to that materialized view and tries to use the function ll_to_earth(float8, float8) it fails because that function either isn't in its search path or hasn't been restored yet, but wouldn't this indicate that the extensions are the first thing to be restored?我知道问题是,当pg_restore到达那个物化视图并尝试使用函数ll_to_earth(float8, float8)它失败了,因为该函数不在其搜索路径中或尚未恢复,但不会这表明扩展是要恢复的第一件事? Can this be fixed?这可以修复吗?

This is part of a script I wrote that will dump the databases on my production environment and restore the databases on my test environment daily so that they match.这是我编写的脚本的一部分,该脚本会将数据库转储到我的生产环境中,并每天在我的测试环境中恢复数据库,以便它们匹配。 It worked for months until I started using this extension, and I'm lost on how to rectify it.它工作了几个月,直到我开始使用这个扩展,我不知道如何纠正它。

For security reasons, pg_dump sets the search_path empty, so only objects in the system schema pg_catalog will be found if they are referenced without schema qualification.出于安全原因, pg_dumpsearch_path设置为空,因此如果在没有模式限定的情况下引用它们,则只会找到系统模式pg_catalog中的对象。

Now your SQL functions uses the data type earth without the schema (probably public ), so you get the error message.现在,您的 SQL 函数使用没有架构(可能是public )的数据类型earth ,因此您会收到错误消息。

You will have to change the function to use qualified names like public.earth for extension objects.您必须更改函数以使用限定名称(如public.earth作为扩展对象。 Alternatively, and probably better, is to fix the search_path for the function:或者,可能更好的是修复该函数的search_path

ALTER FUNCTION myfun SET search_path = public;

This is a good idea anyway, because otherwise your function will cease to work if a user changes search_path .无论如何,这是一个好主意,否则如果用户更改search_path ,您的功能将停止工作。 Depending on the way your function is defined or used, this can even constitute a security problem (which is why pg_dump does it this way).根据定义或使用函数的方式,这甚至可能构成安全问题(这就是pg_dump这样做的原因)。

I found a way around in this answer .我在这个答案中找到了解决方法。 I create extensions in pg_catalog scheme, which is as documentation states always effectively part of the search path .我在pg_catalog方案中创建扩展,正如文档所述,它始终有效地成为搜索路径的一部分

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

People consider this a bad practice, because it might pollute system catalog etc. But it serves me well in my use case - now I can pg_dump/pg_restore without worries.人们认为这是一种不好的做法,因为它可能会污染系统目录等。但它在我的用例中对我很有帮助——现在我可以不用担心 pg_dump/pg_restore。

Note: I found this thread containing a patch for earthdistance extension.注意:我发现这个线程包含一个用于earthdistance扩展的补丁。 Unfortunately it hasn't been merged yet.不幸的是,它还没有被合并。

Had the same problem, however solutions above didn't work.有同样的问题,但是上面的解决方案不起作用。 During data insertion I got the following error在数据插入过程中出现以下错误

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

In pgdump file I had to replace the following line (at the top of the file)在 pgdump 文件中,我必须替换以下行(在文件顶部)

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

With

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM