Theo như tôi biết, không có cơ chế tích hợp nào để xử lý các lỗi của PostgreSQL tùy chỉnh. Tuy nhiên, bạn có thể làm điều đó ở cấp kho lưu trữ.
Để làm điều đó, bạn phải tạo ra các lỗi trong PostgreSQL bằng cách sử dụng ERRCODE
như:
RAISE '[message for logs]' USING ERRCODE = 'integrity_constraint_violation';
và sau đó xử lý chúng trong ứng dụng:
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
Lưu ý lỗi {:error, %{changeset | valid?: false}}
phản ứng. Có nghĩa là tại thời điểm đó, sẽ không có bất kỳ thông báo hữu ích nào để hiển thị.
PS, bạn có thể viết một số macro để ghi đè các chức năng của Ecto và ẩn việc triển khai ở đó (thay vì giải pháp được đề xuất) nhưng tôi tin rằng nó sẽ khó duy trì hơn nhiều.