我在Postgresql中创建了一个自定义函数,该函数在插入或更新之前检查数据,并在出现问题时引发错误。
CREATE FUNCTION custom_check() RETURNS TRIGGER AS $$
BEGIN
IF <SOME CONDITION> THEN
RAISE EXCEPTION 'CUSTOM ERROR';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql
""")
在Postgresql中使用约束时,我可以处理因Ecto.Changeset.check_constraint
而引起的错误。
但是我没有找到一种方法来处理我提出的该错误,以将其反映在变更集中,而不是获取异常并可能将其捕获到我的代码中。
对于Ecto.Changeset.check_constraint
,我应该以其他方式提出错误来处理它,还是以其他方式进行其他事情?
答案 0 :(得分:1)
据我所知,没有内置的机制可以处理自定义PostgreSQL的错误。但是,您可以在存储库级别执行此操作。
为此,您必须使用ERRCODE
在PostgreSQL中引发错误,例如:
RAISE '[message for logs]' USING ERRCODE = 'integrity_constraint_violation';
,然后在应用程序中处理它们:
defmodule Core.Repo do
use Ecto.Repo, otp_app: :core
defoverridable insert: 2
def insert(changeset, opts) do
super(changeset, opts)
rescue
exception in Postgrex.Error ->
handle_postgrex_exception(exception, __STACKTRACE__, changeset)
end
# ... other functions
defp handle_postgrex_exception(exception, stacktrace, changeset \\ nil)
defp handle_postgrex_exception(%{postgres: %{code: :integrity_constraint_violation}}, _, nil) do
{:error, :integrity_constraint_violation}
end
defp handle_postgrex_exception(
%{postgres: %{code: :integrity_constraint_violation}},
_,
changeset
) do
{:error, %{changeset | valid?: false}}
end
defp handle_postgrex_exception(exception, stacktrace, _) do
reraise(exception, stacktrace)
end
end
请注意{:error, %{changeset | valid?: false}}
响应。这意味着到那时,将不会显示任何有用的消息。
PS,您可能可以编写一些宏来覆盖Ecto的功能并在其中隐藏实现(而不是所提出的解决方案),但是我认为这将很难维护。