PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment générer une erreur Postgresql personnalisée et la gérer dans Ecto

Autant que je sache, il n'y a pas de mécanisme intégré pour gérer les erreurs personnalisées de PostgreSQL. Cependant, vous pouvez le faire au niveau du référentiel.

Pour ce faire, vous devez générer des erreurs dans PostgreSQL en utilisant ERRCODE comme :

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

puis les gérer dans l'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

Notez le {:error, %{changeset | valid?: false}} réponse. Cela signifie qu'à ce stade, il n'y aura plus de message utile à afficher.

PS, vous pourriez probablement écrire des macros pour remplacer les fonctions d'Ecto et y masquer l'implémentation (au lieu de la solution proposée) mais je pense que ce serait beaucoup plus difficile à maintenir.