PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie man einen benutzerdefinierten Postgresql-Fehler auslöst und in Ecto behandelt

Soweit ich weiß, gibt es keinen integrierten Mechanismus zur Behandlung von benutzerdefinierten PostgreSQL-Fehlern. Sie können dies jedoch auf Repository-Ebene tun.

Dazu müssen Sie Fehler in PostgreSQL mit ERRCODE auslösen wie:

RAISE '[message for logs]' USING ERRCODE = 'integrity_constraint_violation';

und handhabe sie dann in der Anwendung:

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

Beachten Sie den {:error, %{changeset | valid?: false}} Antwort. Das bedeutet, dass an diesem Punkt keine nützliche Nachricht angezeigt werden kann.

PS Sie könnten wahrscheinlich einige Makros schreiben, um die Funktionen von Ecto zu überschreiben und die Implementierung dort zu verstecken (anstelle der vorgeschlagenen Lösung), aber ich glaube, es wäre viel schwieriger zu warten.