如何引发自定义Postgresql错误并在ecto中处理 [英] How to raise custom Postgresql error and handle it in Ecto
问题描述
我在Postgresql中创建了一个自定义函数,该函数在插入或更新之前检查数据,并在出现问题时引发错误。
I created a custom function in Postgresql that checks data before insert or update and raises error if something goes wrong.
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
引发的错误。
When I'm using constraints in Postgresql, I can handle errors raised with Ecto.Changeset.check_constraint
.
但是我没有找到处理我提出的错误的一种方法,将其反映在changeset中,而不是获取异常,并且可能将其捕获到我的代码中。
But I didn't find a way to handle this error I'm raising, to reflect it in changeset instead of getting an exception and probably catching it inside my code.
我应该以其他方式提出错误 Ecto.Changeset.check_constraint
来处理它,还是做其他事情?
Should I raise error differently for Ecto.Changeset.check_constraint
to handle it, or do differently something else?
推荐答案
据我所知,没有内置的机制可以处理自定义PostgreSQL的错误,但是,您可以在存储库级别进行操作。
As far as I know, there is no built-in mechanism for handling custom PostgreSQL's errors. However, you can do it at the repository level.
要做那,您必须使用 ERRCODE
在PostgreSQL中引发错误,例如:
To do that, you have to raise errors in the PostgreSQL using ERRCODE
like:
RAISE '[message for logs]' USING ERRCODE = 'integrity_constraint_violation';
,然后处理它们应用程序:
and then handle them in the application:
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 |有效吗?:false}}
响应。这意味着到那时,将不会显示任何有用的消息。
Note the {:error, %{changeset | valid?: false}}
response. It means that at that point, there won't be any useful message to display.
PS,您可能可以编写一些宏来覆盖Ecto的功能并在其中隐藏实现(而不是建议的解决方案),但我认为这将很难维护。
PS you could probably write some macros to override Ecto's functions and hide the implementation there (instead of the proposed solution) but I believe it would be much harder to maintain.
这篇关于如何引发自定义Postgresql错误并在ecto中处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!