PostgreSQL:如何简化函数存在时执行逻辑,避免重复fallback代码?
优化PostgreSQL table_version扩展的字段添加逻辑
我有一段基于table_version扩展的字段添加代码,但存在重复编写ALTER TABLE语句的问题:
DO $$ BEGIN -- 如果表已版本化,使用table_version API添加字段 IF EXISTS ( SELECT 1 FROM pg_catalog.pg_proc JOIN pg_catalog.pg_namespace ON pg_namespace.oid = pg_proc.pronamespace WHERE pg_proc.proname = 'ver_is_table_versioned' AND pg_namespace.nspname = 'table_version' ) THEN IF table_version.ver_is_table_versioned('my_schema', 'my_table') THEN PERFORM table_version.ver_versioned_table_add_column( 'my_schema', 'my_table', 'my_column', 'CHAR(1)' ); RETURN; ELSE ALTER TABLE my_schema.my_table ADD COLUMN my_column CHAR(1); END IF; END IF; -- 否则直接执行ALTER TABLE ALTER TABLE my_schema.my_table ADD COLUMN my_column CHAR(1); END; $$
直接使用IF EXISTS(…) AND table_version.ver_is_table_versioned(…)的写法不可行——PostgreSQL会提前解析所有表达式,即使扩展未安装,也会尝试解析table_version相关函数,导致报错:
schema "table_version" does not exist
之前的相关方案要么无法解决该问题,要么通过捕获自定义异常+undefined_function异常来执行 fallback 逻辑,复杂度太高。
优化方案
通过引入布尔标记变量,将重复的ALTER TABLE逻辑统一到一处执行,避免代码冗余:
DO $$ DECLARE needs_alter BOOLEAN := TRUE; BEGIN -- 检查table_version扩展是否已安装 IF EXISTS ( SELECT 1 FROM pg_catalog.pg_proc JOIN pg_catalog.pg_namespace ON pg_namespace.oid = pg_proc.pronamespace WHERE pg_proc.proname = 'ver_is_table_versioned' AND pg_namespace.nspname = 'table_version' ) THEN -- 仅当扩展存在时,才调用其检查函数 IF table_version.ver_is_table_versioned('my_schema', 'my_table') THEN PERFORM table_version.ver_versioned_table_add_column( 'my_schema', 'my_table', 'my_column', 'CHAR(1)' ); -- 已通过扩展API添加字段,无需执行原生ALTER TABLE needs_alter := FALSE; END IF; END IF; -- 统一执行原生字段添加逻辑(仅当未通过扩展API处理时) IF needs_alter THEN ALTER TABLE my_schema.my_table ADD COLUMN my_column CHAR(1); END IF; END; $$
思路说明
- 初始化布尔变量
needs_alter为TRUE,标记默认需要执行原生ALTER TABLE操作 - 先检查table_version扩展是否存在:
- 若存在,进一步判断目标表是否已版本化:
- 若是,调用扩展API添加字段,并将
needs_alter设为FALSE
- 若是,调用扩展API添加字段,并将
- 若存在,进一步判断目标表是否已版本化:
- 最后统一检查
needs_alter状态,仅当标记为TRUE时执行一次ALTER TABLE
这种方式既避免了重复代码,又规避了PostgreSQL提前解析表达式导致的报错问题,逻辑简洁易维护。
内容的提问来源于stack exchange,提问作者l0b0
相关产品推荐
相关产品推荐

