PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como gerar um erro personalizado do Postgresql e tratá-lo no Ecto


Até onde eu sei, não existe um mecanismo embutido para lidar com erros personalizados do PostgreSQL. No entanto, você pode fazer isso no nível do repositório.

Para fazer isso, você deve gerar erros no PostgreSQL usando ERRCODE Curti:
RAISE '[message for logs]' USING ERRCODE = 'integrity_constraint_violation';

e, em seguida, trate-os no aplicativo:
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

Observe o {:error, %{changeset | valid?: false}} resposta. Isso significa que, nesse ponto, não haverá nenhuma mensagem útil para exibir.

PS você provavelmente poderia escrever algumas macros para substituir as funções do Ecto e ocultar a implementação lá (em vez da solução proposta), mas acredito que seria muito mais difícil de manter.