前言:本文介绍了如何在PostgreSQL中实现类似Sybase的host_name函数,旨在帮助开发者解决PG迁移过程中遇到的函数兼容性问题。
Sybase有一个特有的host_name()函数,光看名字容易误解为获取服务器的host name,但实际上这个函数是返回客户端的host name的。上个官方文档:
host_name, a system function, returns the current host computer name of the client process (not the server process).
当前项目中,约有20多个存储过程用到了这个函数,主要用途有三个:
- 做audit log
根据host name进行授权
根据host name更新数据
但PG是没有相对应的函数,因此需要在PG实现该函数。PG中最接近host_name的函数是获取client的ip函数inet_client_addr()。我们可以利用这个函数实现Sybase的host_name函数功能。
方案一
总体思路在数据库中建立并维护一张ip到host name的关系表,然后通过查表获得客户端host name。步骤如下:
创建ip2hostname表。
CREATE TABLE ip2hostname(
hostname varchar(255),
ip varchar(255)
)
2. 创建host_name() 函数。
Create or replace function host_name()
Returns varchar
Language plpgsql
AS $$
Declare v_ip varchar;
v_hostname varchar;
BEGIN
SELECT inet_client_addr() INTO v_ip;
Select hostname into v_hostname from ip2hostname where ip=v_ip;
RETURN COALESCE(v_hostname, 'Unkown');
END;
$$;
这样,host_name()函数就能顺利在PG中运行了。但本方案的缺点也是很明显的,需要人工维护这个映射表,如果网络中采用了DHCP动态IP地址分配,情况会更加复杂。
方案二
方案二是基于方案一的改进版,通过客户端应用主动发送host name到数据库,来消除人工维护映射表的工作。步骤如下:
创建ip2hostname表和host_name() 函数,同方案一。
创建set_host_name()函数。
CREATE OR REPLACE FUNCTION set_host_name(p_hostname text)
RETURNS void AS $$
DECLARE found_count integer;
BEGIN
UPDATE ip2hostname SET ip = inet_client_addr() WHERE hostname = p_hostname;
GET DIAGNOSTICS found_count = ROW_COUNT;
IF found_count = 0 THEN
INSERT INTO ip2hostname (hostname, ip) VALUES (p_hostname, inet_client_addr());
END IF;
END;
$$ LANGUAGE plpgsql;
3. 修改Application,在Application启动后,调用一次set_host_name()函数。
如果客户端是采用Springboot框架开发,可以继承ApplicationRunner,该类会在Springboot启动后,自动运行。
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Autowired
JdbcTemplate jdbcTemplate;
@Override
public void run(ApplicationArguments args) throws Exception {
String hostname= InetAddress.getLocalHost().getHostName();
jdbcTemplate.execute("select set_host_name('"+hostname+"')");
}
}
这样,当应用程序正常启动后,会向数据库中的ip2hostname表插入或更新客户端的host name,后面无论何处执行host_name()函数,都能正确返回客户端的host name了。
总的来说,方案一适用于固定不变的网络环境;方案二适用于偶有变化或频繁变化的网络环境。