我正面临一个绝对奇怪的问题,感觉更像是 Postgres 错误而不是算法问题。
我有这个功能:
CREATE FUNCTION sp_connect(mail character varying, passwd character varying, role character varying)
RETURNS json LANGUAGE plpgsql STABLE AS
$$
DECLARE
user_info record;
BEGIN
IF role = 'Role1' THEN
SELECT u.id, r.name INTO user_info
FROM users u
INNER JOIN users_roles ur ON ur.user_id = u.id
INNER JOIN roles r ON ur.role_id = r.id
WHERE u.email = mail
AND u.password = encode(digest(CONCAT(passwd, u.password_salt), 'sha512'), 'hex')
AND r.name = 'Role1';
ELSIF role = 'Role2' THEN
SELECT h.id, 'Role1' AS name INTO user_info
FROM history h
WHERE h.email = mail
AND h.password = encode(digest(CONCAT(passwd, h.password_salt), 'sha512'), 'hex');
ELSE
RAISE 'USER_NOT_FOUND';
END IF;
IF NOT FOUND THEN
RAISE 'USER_NOT_FOUND';
ELSE
RETURN row_to_json(row) FROM (SELECT user_info.id AS id, user_info.name AS role) row;
END IF;
END;
$$;
我面临的问题是,当我使用此功能以 Role1 用户登录时,当我将其与 Role2 用户一起使用时,我收到以下错误消息:
type of parameter 7 (character varying) does not match that when preparing the plan (unknown)
这是……嗯,我只是不明白它是从哪里来的。如果您擦除数据库并更改登录顺序(即 Role2 然后 Role1),这一次,Role1 得到错误。
奇怪的问题,奇怪的解决方案......如果我只是使用ALTER FUNCTION sp_connect
但没有修改函数内部的任何内容,那么神奇地,两个角色可以毫无问题地登录。我也试过这个解决方案:
IF NOT FOUND THEN
RAISE 'USER_NOT_FOUND';
ELSE
IF role = 'Seeker'
THEN
RETURN row_to_json(row) FROM (SELECT user_info.id AS id, user_info.name AS role) row;
ELSE
RETURN row_to_json(row) FROM (SELECT user_info.id AS id, user_info.name AS role) row;
END IF;
IF
并且通过添加一个ELSE
绝对没用的 and 并使用相同的 RETURN 子句,这不会触发任何错误。
我知道 DBA StackExchange 不适合开发人员,但这种问题似乎更像是缓存问题或其他问题。有人可以告诉我我是否对 PostgreSQL 函数做错了什么吗?或者我可以在哪里获得解决这个奇怪问题的帮助?