具有嵌套IF的Postgres函数

时间:2016-09-29 23:59:26

标签: postgresql function postgresql-9.5

我有一个功能,我试图创建一个用户,将用户插入一个表,并提供IF将用户添加到角色。我可以创建用户并将其添加到我使用第一个功能创建的表格中,但是我无法有条件地将它们添加到组中。我希望选项不将用户添加到角色或包含角色并将该角色授予用户。这是我创建工作的用户的功能

.compose(deoptionalize())

我想做类似伪代码的事情

CREATE OR REPLACE FUNCTION create_user(
    new_user character varying,
    temp_password character varying,
    grant_role text default NULL)
  RETURNS text AS
$BODY$
BEGIN
   IF NOT EXISTS (SELECT usename FROM pg_catalog.pg_user
        Where  usename not in ('postgres','repl','pgpool')
        and usename = new_user) THEN
        EXECUTE format('CREATE USER ' || new_user || ' with password ''' || temp_password || ''';');
        EXECUTE format('insert into open_sesame (user_name, last_change_date, next_change_date) VALUES( '''  || new_user || ''',
        date(now()),
        date(now() + interval ''1 days''));');
        RETURN 'CREATED ROLE';
   ELSE
        RETURN format('ROLE ''%I'' ALREADY EXISTS', new_user);
END IF;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE SECURITY DEFINER
  COST 100;
ALTER FUNCTION create_user(character varying, character varying)
  OWNER TO postgres;

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

您缺少嵌套IF ... THEN ... [ELSEIF ...] [ELSE ...] END IF; 的条件。填写我已添加注释行的位置,它应该按预期使用嵌套

BEGIN
 IF NOT EXISTS (
  SELECT usename 
  FROM pg_catalog.pg_user
  WHERE usename not in ('postgres','repl','pgpool')
    AND usename = new_user
  ) 
  THEN
    IF NOT EXISTS (
      SELECT rolname 
      FROM pg_roles 
      WHERE rolname = grant_role
        AND rolname <> 'postgres'
    ) AND grant_role IS NOT NULL 
    THEN
      EXECUTE format('CREATE USER ' || new_user || ' with password ''' || temp_password || ''';');
      EXECUTE format('GRANT ' || grant_role || ' to ' || new_user ||';');
      EXECUTE format('insert into open_sesame (user_name, last_change_date, next_change_date) VALUES( '''  || new_user || ''', date(now()), date(now() + interval ''1 days''));');
      RETURN 'CREATED USER WITH ROLE';
    ELSEIF -- you forgot to specify the condition
      EXECUTE format('CREATE USER ' || new_user || ' with password ''' || temp_password || ''';');
      EXECUTE format('insert into open_sesame (user_name, last_change_date, next_change_date) VALUES( '''  || new_user || ''', date(now()),date(now() + interval ''1 days''));');
      RETURN 'CREATED USER ONLY';
    ELSE
      RETURN 'NO USER CREATED';  
    END IF;
  ELSE
    RETURN format('ROLE ''%I'' ALREADY EXISTS', new_user);
  END IF;
END;

代码:

[RoutePrefix("api/APILogin")]
public class APILoginApiController {
    [Route("", Name = "Login")]
    public ActionResult Login(string userName) {
        // ...
    }
}

答案 1 :(得分:0)

我最终将@Kamil G.的答案修改为以下函数。他的回答让我到了我需要的地方。

CREATE OR REPLACE FUNCTION create_user(
    new_user character varying,
    temp_password character varying,
    grant_role text default NULL)
  RETURNS text AS
$BODY$
BEGIN
    IF NOT EXISTS (
        SELECT usename
        FROM pg_catalog.pg_user
        WHERE usename not in ('postgres','repl','pgpool')
        AND usename = new_user
        ) AND grant_role IS NOT NULL
    THEN
        IF EXISTS (
            SELECT rolname
            FROM pg_roles
            WHERE rolname = grant_role
            AND rolname <> 'postgres'
        )
        THEN
            EXECUTE format('CREATE USER ' || new_user || ' with password ''' || temp_password || ''';');
            EXECUTE format('GRANT ' || grant_role || ' to ' || new_user ||';');
            EXECUTE format('insert into open_sesame (user_name, last_change_date, next_change_date) VALUES( '''  || new_user || ''', date(now()), date(now() + interval ''1 days''));');
            RETURN 'CREATED USER WITH ROLE';
        ELSE
            RETURN 'NO USER CREATED';
        END IF;
    ELSEIF NOT EXISTS (
            SELECT rolname
            FROM pg_roles
            WHERE rolname = grant_role
            AND rolname <> 'postgres'
        ) AND grant_role IS NULL
    THEN
        EXECUTE format('CREATE USER ' || new_user || ' with password ''' || temp_password || ''';');
        EXECUTE format('insert into open_sesame (user_name, last_change_date, next_change_date) VALUES( '''  || new_user || ''', date(now()),date(now() + interval ''1 days''));');
        RETURN 'CREATED USER ONLY';
    ELSE
        RETURN 'NO USER CREATED';
    END IF;
END;