PostgreSQL: Using pgsql_fdw in a funnction Result ,ERROR: cache lookup failed for type 0

今天读德哥 blog (原文 http://blog.163.com/digoal@126/blog/static/16387704020125218171919/ ),里面描述的问题引起了我的好奇,问题是这样的,在 function 中 使用 pgsql_fdw 调用pg远程外部表时,会报错,而在 session 中不会,具体演示下。

环境信息

源库:
IP 192.168.1.26/1923
database mydb
table test
1.2 目标库
IP 192.168.1.26/1923
database skytf
table test_tf
备注: 关于 pgsql_fdw 安装略,可以参考之前写的 BLOG:https://postgres.fun/20120607112420.html

目标库表信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mydb=> /d test  
Table "mydb.test"
Column | Type | Modifiers
--------+-----------------------+-----------
id | integer |
name | character varying(32) |
Indexes:
"idx_test_1" btree (id)

mydb=> select count(*) from test;
count
---------
1990000
(1 row)

版本信息
pgsql_fdw 模块版本:pgsql_fdw-1.0
postgresql 版本: PostgreSQL 9.1.0

外部表测试

2.1 create foreign server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
skytf=> /c skytf postgres  
You are now connected to database "skytf" as user "postgres".

skytf=# grant usage on foreign data wrapper pgsql_fdw to skytf;
GRANT

skytf=# /c skytf skytf
You are now connected to database "skytf" as user "skytf".

skytf=> CREATE SERVER pgsql_srv FOREIGN DATA WRAPPER pgsql_fdw
skytf-> OPTIONS (host '127.0.0.1', port '1923', dbname 'mydb');
CREATE SERVER

skytf=> /des
List of foreign servers
Name | Owner | Foreign-data wrapper
--------------+-------+----------------------
file_srv | skytf | file_fdw
mysql_svr_25 | skytf | mysql_fdw
pgsql_srv | skytf | pgsql_fdw
(3 rows)

create mapping user

1
2
3
skytf=> CREATE USER MAPPING FOR public SERVER pgsql_srv  
skytf-> OPTIONS (user 'mydb', password 'mydb');
CREATE USER MAPPING

create foreign table

1
2
3
4
5
6
skytf=> CREATE FOREIGN TABLE ft_test (  
skytf(> id integer ,
skytf(> name character varying(32) )
skytf-> SERVER pgsql_srv
skytf-> OPTIONS (nspname 'mydb', relname 'test');
CREATE FOREIGN TABLE

查询外部表测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
skytf=> /d ft_test;  
Foreign table "skytf.ft_test"
Column | Type | Modifiers
--------+-----------------------+-----------
id | integer |
name | character varying(32) |
Server: pgsql_srv

skytf=> select * From ft_test limit 3;
id | name
-------+------
54241 | AAA
54242 | AAA
54243 | AAA
(3 rows)

创建中间表

1
2
skytf=> create table test_tf (id int4,name varchar(32));  
CREATE TABLE

创建函数

1
2
3
4
5
6
7
8
CREATE or replace FUNCTION func_sync_bill() RETURNS INTEGER AS $$  
BEGIN
begin
insert into test_tf (id,name) select id,name from ft_test;
return 0;
end;
END;
$$ LANGUAGE 'plpgsql';

执行函数

1
2
3
4
5
6
7
8
9
10
skytf=> select func_sync_bill() ;  
ERROR: cache lookup failed for type 0
CONTEXT: SQL statement "insert into test_tf (id,name) select id,name from ft_test"
PL/pgSQL function "func_sync_bill" line 4 at SQL statement

skytf=> select count(*) from test_tf;
count
-------
0
(1 row)

备注:错误出现在语句 “insert into test_tf (id,name) select id,name from ft_test” 而这个语句单独在 session 中执行是正确的。

2.8 在会话中执行插入语句

1
2
3
4
5
6
7
8
skytf=> select count(*) from test_tf;  
count
-------
0
(1 row)

skytf=> insert into test_tf (id,name) select id,name from ft_test;
INSERT 0 1990000

备注:在 seesion 中调用 pgsql_fdw 表是正常的,而在 plpgsql function 中却不行, 之后网上查了很多资料也没有相关 bug 确认信息,后来 dba.stackexchange.com 问了下,有人建议使用 “EXCUTE” 语句,原贴如下 http://dba.stackexchange.com/questions/19919/using

使用 EXCUTE 测试 pgsql_fdw

创建 function

1
2
3
4
5
6
7
8
9
skytf=> CREATE or replace FUNCTION func_sync_bill() RETURNS INTEGER AS $$  
skytf$> BEGIN
skytf$> begin
skytf$> EXECUTE 'insert into test_tf (id,name) select id,name from ft_test';
skytf$> return 0;
skytf$> end;
skytf$> END;
skytf$> $$ LANGUAGE 'plpgsql';
CREATE FUNCTION

再次测试

1
2
3
4
5
6
7
8
9
10
11
12
skytf=> truncate table test_tf;  
TRUNCATE TABLE
skytf=> select func_sync_bill();
func_sync_bill
----------------
0
(1 row)
skytf=> select count(*) from test_tf;
count
---------
1990000
(1 row)

备注:在 function 中采用 EXECUTE 语句执行后报错消失,估计 pgsql_fdw 模块目前还不很成熟,如果需要查询远程库数据的需求,也可以用比较原始的方法,即 dblink 来代替 pgsql_fdw。

原创文章,作者:506227337,如若转载,请注明出处:https://blog.ytso.com/237878.html

(0)
上一篇 2022年1月29日
下一篇 2022年1月29日

相关推荐

发表回复

登录后才能评论