PostgreSQL создает представления и импортирует внешнюю схему в одной транзакции

Я установил postgres_fdw между двумя базами данных (sourcedb, targetdb), чтобы я мог создавать таблицы внешних данных в targetdb из схемы в sourcedb.

Все вышеперечисленное настроено и работает как положено.

Следующим шагом был повторный импорт внешней схемы каждый раз, когда у меня происходят изменения в представлениях в sourcedb.

Для этого я создал две функции в sourcedb:

  1. fn_create_views
  2. fn_recreate_foreign_data_tables

В первой функции (fn_create_views) я динамически создаю представления в цикле. После завершения цикла я вызываю вторую функцию, которая удаляет все таблицы внешних данных и импортирует внешнюю схему через dblink, подключающийся к targerdb.

CREATE FUNCTION fn_create_views ()
RETURNS BOOLEAN
LANGUAGE plpgsql
as $$

BEGIN

 FOR .. IN
  EXECUTE '..'
 LOOP

  EXECUTE format('CREATE OR REPLACE VIEW .. AS
                  SELECT * FROM ...', params);

 END LOOP;

 PERFORM fn_recreate_foreign_data_tables('source_foreign_server','target_foreign_server');

return true;

END $$;
CREATE FUNCTION fn_recreate_foreign_data_tables(_source_foreign_server varchar, _targer_foreign_server varchar)
returns void
language plphsql
as $$

DECLARE 

 _sql_exec text;

BEGIN

 _sql_exec := (SELECT format('SELECT public.dblink_exec(%L,
                    ''DO
                    $dblink$
                    DECLARE
                      l_rec record;
                    BEGIN
                      FOR l_rec IN (SELECT foreign_table_schema, foreign_table_name
                                    FROM information_schema.foreign_tables
                                    WHERE foreign_server_name = ''%L'')
                      LOOP
                         EXECUTE format(''''drop foreign table %I.%I'''', l_rec.foreign_table_schema, l_rec.foreign_table_name);
                      END LOOP;

                      IMPORT FOREIGN SCHEMA ..
                      FROM SERVER foreign_server INTO ..;

                    END $dblink$;'')', _source_foreign_server, _target_foreign_server));

 EXECUTE _sql_exec;

end $$;

Проблема, с которой я столкнулся в связи с вышеизложенным, заключается в том, что во время «ИМПОРТНОЙ ВНЕШНЕЙ СХЕМЫ» «СОЗДАТЬ ВИД» в результате не фиксируется, хотя все сторонние таблицы удаляются, он ничего не импортирует в схему targetdb.

После прочтения нескольких сообщений здесь, в SO, некоторые рекомендуют запускать команду CREATE VIEW через dblink в той же БД. По-видимому, это работает отлично, так как я думаю, что dblink каждый раз будет открывать отдельную транзакцию.

Теперь мой вопрос: есть ли другой более простой способ сделать это без отдельного вызова вышеуказанных функций?

Благодарю вас!


person Giannis Dim    schedule 11.12.2019    source источник
comment
Что это за взгляды? Удаление внешних таблиц и их повторное создание в той же транзакции должно работать нормально.   -  person Laurenz Albe    schedule 11.12.2019
comment
@LaurenzAlbe представления представляют собой простые запросы на выборку по материализованному представлению. Целью вышеперечисленных функций является повторное развертывание всех зависимостей материализованного представления каждый раз, когда я хочу внести изменение в запрос материализованного представления.   -  person Giannis Dim    schedule 12.12.2019
comment
@LaurenzAlbe Удаление и создание внешних таблиц отлично работает в одной и той же транзакции. Но я хочу создавать представления, удалять и создавать внешние таблицы в одной и той же транзакции.   -  person Giannis Dim    schedule 12.12.2019
comment
Какая именно связь между представлениями и внешними таблицами? Используют ли определения представлений сторонние таблицы?   -  person Laurenz Albe    schedule 12.12.2019
comment
@LaurenzAlbe И наоборот, внешние таблицы указывают на каждое представление в sourcedb. Я создаю все представления в схеме, которая импортируется с помощью следующей команды IMPORT FOREIGN SCHEMA..   -  person Giannis Dim    schedule 12.12.2019


Ответы (1)


Вам нужно выполнить COMMIT локальную транзакцию, в которой вы создаете представления, прежде чем вы сможете использовать их с внешними таблицами.

Я вижу два варианта:

  • Создайте представления в dblink вызове локальной базы данных. Затем транзакция будет зафиксирована, когда dblink_exec будет выполнено.

  • Запустите COMMIT между вызовами fn_create_views и fn_recreate_foreign_data_tables.

person Laurenz Albe    schedule 12.12.2019
comment
Благодарю вас! Я, вероятно, выберу второй вариант и создам функцию-оболочку и вызову две функции по отдельности. - person Giannis Dim; 13.12.2019