PostgreSQLOracle相容性-synonym匿名

德哥發表於2017-10-28

標籤

PostgreSQL , 匿名 , 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的方法。


相關文章