如何在PostgreSQL的MY_ENCRYPT函数中获取MYTYPE列的TYPMOD值?
在PostgreSQL函数中获取自定义类型的TYPMOD值
核心结论
默认情况下,PostgreSQL的函数无法直接从传入的自定义类型实例中获取列定义时的TYPMOD(即你示例中的X值),因为TYPMOD是列级别的元数据属性,不属于类型实例本身的内容。不过可以通过以下两种方式实现需求:
方法1:将TYPMOD作为额外参数传入加密函数
修改MY_ENCRYPT函数,增加一个整数参数用于接收TYPMOD值:
CREATE OR REPLACE FUNCTION MY_ENCRYPT(val mytype, typmod integer) RETURNS mytype AS $$ BEGIN -- 在这里使用typmod值检查加密后的数据大小 IF 加密后的数据长度 > (typmod - 加密开销) THEN RAISE EXCEPTION '加密后数据超出允许范围'; END IF; -- 执行3DES加密逻辑 RETURN 加密结果; END; $$ LANGUAGE plpgsql;
调用函数时,先从系统表中查询目标列的TYPMOD(注意:部分类型的atttypmod会有固定偏移,需根据MYTYPE的定义调整):
-- 查询t0表c0列的真实typmod值 SELECT atttypmod - 4 FROM pg_attribute WHERE attrelid = 't0'::regclass AND attname = 'c0'; -- 调用加密函数时传入该值 UPDATE t0 SET c0 = MY_ENCRYPT(c0, 80) WHERE ...;
方法2:通过触发器自动传递TYPMOD
如果希望在数据写入时自动完成检查和加密,可以创建触发器,在触发器中获取列的TYPMOD并调用加密函数:
CREATE OR REPLACE FUNCTION t0_encrypt_trigger() RETURNS trigger AS $$ DECLARE col_typmod integer; BEGIN -- 获取当前列的typmod SELECT atttypmod - 4 INTO col_typmod FROM pg_attribute WHERE attrelid = TG_RELID AND attname = 'c0'; -- 调用加密函数并传入typmod NEW.c0 = MY_ENCRYPT(NEW.c0, col_typmod); RETURN NEW; END; $$ LANGUAGE plpgsql; -- 绑定触发器到t0表 CREATE TRIGGER t0_encrypt_trigger BEFORE INSERT OR UPDATE ON t0 FOR EACH ROW EXECUTE FUNCTION t0_encrypt_trigger();
关键说明
- 系统表
pg_attribute中的atttypmod字段,对于部分内置类型(如varchar)会包含固定偏移(比如varchar(n)的atttypmod是n+4),你需要根据自己定义的MYTYPE的实现逻辑,调整获取到的atttypmod值,得到真实的X。 - 由于你的
MYTYPE是通用类型,无法修改其结构嵌入TYPMOD,上述两种方法都是在类型外部传递元数据,符合你的需求。
内容的提问来源于stack exchange,提问作者TheBadCat
相关产品推荐
相关产品推荐

