В PostgreSQL 11 я регулярно сбрасываю резервные снимки и иногда импортирую их в систему разработки с одинаковыми настройками.Ничего особенного:
# Dump
ps_dump -OU <user> <database> >dump.sql
# Restore
psql -U <user> -f dump.sql <database>
Однако два индекса в дампе выдают ошибки при восстановлении.Я свел его к следующему дампу со всем несвязанным удаленным:
--
-- PostgreSQL database dump
--
-- Dumped from database version 11.2
-- Dumped by pg_dump version 11.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 client_min_messages = warning;
SET row_security = off;
--
-- Name: add_days(timestamp without time zone, integer, text); Type: FUNCTION; Schema: public; Owner: -
--
CREATE FUNCTION public.add_days(timestamp without time zone, integer, text DEFAULT 'Europe/Zurich'::text) RETURNS timestamp without time zone
LANGUAGE sql IMMUTABLE
SET search_path TO 'public', 'pg_temp'
AS $_$
SELECT (($1::timestamp AT TIME ZONE 'UTC' AT TIME ZONE $3 + INTERVAL '1 day' * $2) AT TIME ZONE $3)::timestamp
$_$;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: projects; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.projects (
id integer NOT NULL,
started_at timestamp without time zone,
duration integer
);
--
-- Name: ended_at(public.projects); Type: FUNCTION; Schema: public; Owner: -
--
CREATE FUNCTION public.ended_at(public.projects) RETURNS timestamp without time zone
LANGUAGE sql STABLE
AS $_$
SELECT add_days($1.started_at, $1.duration)
$_$;
--
-- Name: index_projects_on_ended_at; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_projects_on_ended_at ON public.projects USING btree (public.ended_at(projects.*));
Восстановление этого дампа приводит к следующей ошибке:
psql:dumped.sql:60: ERROR: function add_days(timestamp without time zone, integer) does not exist
LINE 2: SELECT add_days($1.started_at, $1.duration)
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
QUERY:
SELECT add_days($1.started_at, $1.duration)
CONTEXT: SQL function "ended_at" during inlining
Следующее исправляет проблему: Префикс add_days
со схемой следующего содержания:
CREATE FUNCTION public.ended_at(public.projects) RETURNS timestamp without time zone
LANGUAGE sql STABLE
AS $_$
SELECT public.add_days($1.started_at, $1.duration)
$_$;
Дело закрыто?Не совсем.Я хотел бы понять, в чем здесь проблема.
Полагаю, строка SELECT pg_catalog.set_config('search_path', '', false);
, сгенерированная pg_dump, не позволяет найти add_days
, если только с явной префиксом схемы.
Однакопочему не работает следующая альтернатива (добавление search_path)?
CREATE FUNCTION public.ended_at(public.projects) RETURNS timestamp without time zone
LANGUAGE sql STABLE
SET search_path TO 'public', 'pg_temp'
AS $_$
SELECT add_days($1.started_at, $1.duration)
$_$;
Это вызывает совершенно другую ошибку:
psql:dumped.sql:58: ERROR: functions in index expression must be marked IMMUTABLE
Хорошо, теперь я запутался.Может кто-нибудь сказать мне, что здесь происходит?