问题描述
我需要在postgresql中编写一个函数,该函数必须根据条件从表中“拾取”整个行,然后将它们插入到数组中,最后返回该数组。
我实际上是在查询我需要的行,但是表中有一个特殊的列,我必须首先对其进行评估,以查看是否可以检索它(插入数组),具体取决于用户执行的操作类型。查询(客户或工作人员)。
例如:
该特殊列名为“观察者”,具有两个变体:“ my_team”和“ only_me”,还具有另一个名为“ user_id”的列。
如果该列显示为“ my_team”,则可以毫无问题地将该行插入阵列,但是如果显示为“ only_me”,则必须比较调用该函数的用户和在该行中注册的用户的ID它们匹配,我可以将其插入数组,否则不能。
事情是,到目前为止,我似乎无法用数组完成它,所以我想知道是否还有另一种方法,也许可以使用额外的表或其他东西? >
感谢您的帮助!
这是我的代码:
CREATE OR REPLACE FUNCTION public.calculates_permission_by_task(task_id integer)
RETURNS SetoF permission
LANGUAGE plpgsql
STABLE
AS $function$
DECLARE
num int := 5;
record permission;
ret_permissions permission [];
BEGIN
FOR record IN (select
p.id,p.slug
from task as t
join service_request_form as srf on t.service_request_form_id = srf.id
join service_group as sg on srf.service_group_id = sg.id
join worker_group as wg on wg.service_group_id = sg.id
join worker_group_member as wgm on wg.id = wgm.worker_group_id
join role as r on r.id = wgm.role_id
join permission_role as pr on r.id = pr.role_id
join permission as p on p.id = pr.permission_id
where t.id = task_id
and wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2'
and pr.value <> 'off'
and pr.value <> 'no')
LOOP
/* Here is where I pretend to do the comparison and insert data into the array */
ret_permission := array_append(ret_permissions,record.id);
END LOOP;
RETURN ret_permissions;
END
$function$
解决方法
您可以在查询本身中实现逻辑。
假设您要引用的user_id
列对应于查询中已经存在的wgm.user_id
,则查询的where
子句将变为:
where
t.id = task_id
and pr.value not in ('off','no')
and (
?.watchers = 'my_team'
or (
?.watchers = 'only_me'
or wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2'
)
)
您不知道watches
属于哪个表,所以我使用了?
,您需要用相关的表别名替换它。
如果watchers
只有两个可能的值,那么我们可以简化谓词:
where
t.id = task_id
and pr.value not in ('off','no')
and (?.watchers = 'my_team' or wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2')
,
- 您不需要数组
- 您不需要游标循环
- 您甚至不需要plpgsql
- 普通的SQL就足够了:
CREATE TABLE permission (
id integer,slug text
);
INSERT INTO permission(id,slug) VALUES (1,'WTF' );
CREATE TABLE task (
id integer,service_request_form_id integer
);
INSERT INTO task(id,service_request_form_id) VALUES (1,1 );
CREATE TABLE service_request_form (
id integer,service_group_id integer
);
INSERT INTO service_request_form(id,service_group_id) VALUES (1,1 );
CREATE TABLE service_group (
id integer
);
INSERT INTO service_group(id) VALUES (1);
CREATE TABLE worker_group (
id integer,service_group_id integer
);
INSERT INTO worker_group(id,1 );
CREATE TABLE worker_group_member (
worker_group_id integer,role_id integer,user_id text
);
INSERT INTO worker_group_member(worker_group_id,role_id,user_id) VALUES (1,1,'LFudaU6jzid4SKFlU8MgFAwezyP2' );
CREATE TABLE zrole (
id integer
);
INSERT INTO zrole(id) VALUES (1 );
CREATE TABLE permission_role (
role_id integer,permission_id integer,value text
);
INSERT INTO permission_role(role_id,permission_id,value) VALUES (1,'Yes' );
CREATE OR REPLACE FUNCTION public.calculates_permission_by_task(task_id integer)
RETURNS SETOF permission
LANGUAGE sql STABLE SECURITY INVOKER ROWS 30 -- COST 1
AS $func$
SELECT p.id,p.slug
FROM permission as p
WHERE EXISTS (
SELECT *
FROM task as t
JOIN service_request_form as srf
on t.service_request_form_id = srf.id
JOIN service_group as sg
on srf.service_group_id = sg.id
JOIN worker_group as wg
on wg.service_group_id = sg.id
JOIN worker_group_member as wgm
on wg.id = wgm.worker_group_id
JOIN zrole as zr
on zr.id = wgm.role_id
JOIN permission_role as pr
on zr.id = pr.role_id
WHERE p.id = pr.permission_id
AND t.id = task_id
and wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2'
and pr.value NOT IN( 'off','no' )
-- -------------------------
-- Add the needed logic
-- (From @GMB) here
-- -------------------------
);
$func$
;
-- Usage:
-- --------------
SELECT * -- p.id,p.slug
FROM public.calculates_permission_by_task(42);