PostgreSQL如何扩展现有数据类型实现类似TypeScript接口继承效果
PostgreSQL扩展返回类型解决方案
特性支持说明
PostgreSQL 原生支持复合类型继承和表继承,完全匹配你需要的「子类型继承父类型全部属性、新增自定义字段」的需求,你期望的类似extends的能力已经有现成实现,不需要手动罗列meeting_instances的全部字段,也不用提前创建视图。
方案1:使用继承表作为返回类型(推荐)
这个方案完全匹配你的使用场景,只需要创建一个空的继承表复用meeting_instances的结构,不需要往里面存储任何数据,后续原表结构变更时子表会自动同步:
-- 创建继承表,自动继承meeting_instances的所有字段,新增自定义字段 CREATE TABLE service_hour ( total float, hours float ) INHERITS (meeting_instances); -- 修改函数返回类型为SETOF service_hour即可 create or replace function user_hours(org_id text, user_id text) returns setof service_hour as $$ select (sum(hours) over (order by _.instance_time)) total, * from ( select extract(epoch from ((meeting_instances.time).to - (meeting_instances.time).from)) / 60 / 60 as hours, meeting_instances.* from meeting_instances inner join relation_people on relation_people.meeting = meeting_instances.id where relation_people.user = user_id and meeting_instances.org = org_id and meeting_instances.instance_time <= current_date ) as _; $$ language sql stable;
调用方式和普通表函数完全一致,直接SELECT * FROM user_hours('org_id','user_id')就能拿到包含原表所有字段+total+hours的扁平化结果。
方案2:使用OUT参数返回嵌套行类型(无需额外建对象)
如果你不想新增任何表/类型对象,可以用OUT参数组合原表行类型的方式实现,调用时按需展开即可:
create or replace function user_hours( org_id text, user_id text, OUT total float, OUT hours float, OUT meeting_data meeting_instances -- 直接用原表作为复合类型 ) returns setof record as $$ select (sum(hours) over (order by _.instance_time)) total, hours, _::meeting_instances from ( select extract(epoch from ((meeting_instances.time).to - (meeting_instances.time).from)) / 60 / 60 as hours, meeting_instances.* from meeting_instances inner join relation_people on relation_people.meeting = meeting_instances.id where relation_people.user = user_id and meeting_instances.org = org_id and meeting_instances.instance_time <= current_date ) as _; $$ language sql stable;
调用时如果需要扁平化结果,写法如下:
SELECT total, hours, (meeting_data).* FROM user_hours('org_id', 'user_id');
补充说明
你期望的RETURNS TABLE直接合并LIKE语法和自定义字段的简写,目前PostgreSQL正式版本还未支持,上述两种方案是当前版本下最简便的实现方式,其中方案1的使用体验和你预想的伪代码几乎一致。
内容的提问来源于stack exchange,提问作者Nicholas Chiang
相关产品推荐
相关产品推荐

