问题
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
""")
When I'm using constraints in Postgresql, I can handle errors raised with Ecto.Changeset.check_constraint
.
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.
Should I raise error differently for Ecto.Changeset.check_constraint
to handle it, or do differently something else?
回答1:
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.
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
Note the {:error, %{changeset | valid?: false}}
response. It means that at that point, there won't be any useful message to display.
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.
来源:https://stackoverflow.com/questions/53122256/how-to-raise-custom-postgresql-error-and-handle-it-in-ecto