如何引发自定义Postgresql错误并在ecto中处理 [英] How to raise custom Postgresql error and handle it in Ecto

查看:134
本文介绍了如何引发自定义Postgresql错误并在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆