3

远程架构:

some_table
some_table_view
some_table_view_trigger (INSTEAD OF INSERT)
    -- tries to access some_table (select/update/insert)

本地架构:

some_table_view_fdw
    -- wraps some_table_view on remote

现在在本地,当我运行INSERTon时some_table_view_fdw,我得到relation not found: some_table.

  • 我可以从 some_table_view_fdw 中选择就好了(some_table_view 只返回 * from some_table)。
  • 如果在本地(在远程)运行,插入到 some_table_view 工作得很好。触发器做了它应该做的事情。
  • 请注意, some_table_view_fdw 没有直接引用 some_table ,所以我猜触发器必须正在运行,但是由于某种原因找不到它自己的表?

我正在使用 postgres 9.3

4

1 回答 1

3

问题源于这样一个事实,即在查询远程服务器search_path参数时设置为pg_catalog. 因此,对架构中的表的引用public不会自动解决。

要解决此问题,请在触发器函数中使用绝对表名public.my_table,例如,而不是my_table. 这也适用于触发器或视图中使用的所有函数和视图。

您也可以search_path在触发功能中进行设置,尽管我不推荐这种解决方案。当触发器在本地触发时,悄悄更改的参数将一直有效,直到会话结束,这可能会导致进一步的混乱。


把它当作一个好奇心:如何检查search_path远程服务器postgres_fdw

使用远程服务器(本地)上的触发器创建测试表:

create table test_path (id int, val text);

create or replace function path_trigger()
returns trigger language plpgsql as $$
begin
    select setting into new.val
    from pg_settings where name = 'search_path';
    return new;
end $$;

create trigger path_trigger
before insert on test_path
for each row execute procedure path_trigger();

insert into test_path (id) values (1) returning *;

 id |      val     
----+----------------
  1 | "$user",public
(1 row)

在本地服务器上创建外部表并触发远程触发器:

create foreign table test_path (id int, val text)
server backup_server
options (schema_name 'public', table_name 'test_path'); 

insert into test_path (id) values (2) returning *;

 id |    val     
----+------------
  2 | pg_catalog
(1 row) 
于 2015-10-04T22:02:54.773 回答