Search code examples
postgresqlpgpg-dumppg-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. 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. I don't really want to try and install an extension to pg_catalog because that seems like poor practice.

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:

--
-- 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? 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? 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.


Solution

  • 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.

    Now your SQL functions uses the data type earth without the schema (probably public), so you get the error message.

    You will have to change the function to use qualified names like public.earth for extension objects. Alternatively, and probably better, is to fix the search_path for the function:

    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. 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).