PostgreSQL Oracle 兼容性 - synonym 匿名
背景
Oracle 的一个功能,支持对其他对象建立别名(匿名:synonym),它有什么用呢?
比如某些业务系统中,代码中写死了要访问的对象是在哪个用户下的。当迁移时,如果遇到用户名冲突,我们可能会选择将对象同步到其他用户下。那么问题来了,程序也要改动,如果是很老的程序,估计找不到人来做这件事情。用synonym(匿名)可以很好的解决这个问题。
匿名语法如下
CREATE [ OR REPLACE ] [ PUBLIC ] SYNONYM
[ schema. ]synonym
FOR [ schema. ]object [ @ dblink ] ;
https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7001.htm
对于状态可变的对象(例如表、序列)来说,匿名可以使用类似于指针引用的方法来实现。对于状态不可变的对象(例如函数、视图),匿名可以拷贝的方式来实现。实际上没有永久不变的东西,函数内容,视图的结构都是可能变化的。
下面给出一些例子,在PostgreSQL中如何实现synonym(非内核实现)。
PostgreSQL synonym的方法
我们可以对多种对象建立匿名,方法各异。
1、表
代码写死了b.tbl123:
create table a.tbl(id int);
通过视图,
create view b.tbl123 as select * from a.tbl;
这种简单视图,支持增删改查,和直接使用a.tbl是一样的。
相当于建立了a.tbl的b.tbl123匿名。
通过search_path,
如果对象名没变,只是在不同的schema下,使用search_path是最通用的方法:
set search_path=a,"$user",public;
那么会先访问a这个schema下的对象。
2、函数
代码写死了b.fun123:
create or replace function a.fun(int) returns int as $$
....
$$ language plpgsql strict;
通过函数嵌套,
create or replace function b.fun123(int) returns int as $$
select a.fun($1);
$$ language sql strict;
通过search_path,与1类似。
3、视图
通过视图,与1类似。
通过search_path
4、物化视图
通过视图,与1类似。
通过search_path,与1类似。
5、DBLINK
通过重定义一样的dblink。
通过search_path,与1类似。
6、外部表
通过视图,与1类似。
通过search_path,与1类似。
7、自定义类型
通过重定义一样的类型。
通过search_path,与1类似。
8、序列
如果名字改变,可以通过覆盖nextval,setval,currval来实现,例子
create or replace function nextval(name) returns int8 as $$
declare
res int8;
begin
if $1='目标seq对象名字' then
select pg_catalog.nextval('已存在seq对象'::regclass) into res;
else
select pg_catalog.nextval($1::regclass) into res;
end if;
return res;
end;
$$ language plpgsql strict;
postgres=# select nextval('已存在seq对象');
nextval
---------
1
(1 row)
postgres=# select nextval('目标seq对象名字');
nextval
---------
2
(1 row)
postgres=# select nextval('已存在seq对象');
nextval
---------
3
(1 row)
如果只是search_path的问题,通过search_path解决,与1方法类似。
内核实现
内核实现当然是最好的,很早以前社区有提过这样的PATCH,有兴趣的同学可以考虑把它port到PG最新的版本来。
https://www.postgresql.org/message-id/440D446E.7040509@cybertec.at
使用了类似HOOK的方法。