Skip to content

Commit ca6f1bc

Browse files
committed
add Ecto.Adapters.MyXQL.Constraint and delegate from the connection
1 parent e5ea9f6 commit ca6f1bc

File tree

3 files changed

+52
-40
lines changed

3 files changed

+52
-40
lines changed

integration_test/myxql/constraints_test.exs

+4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ defmodule Ecto.Integration.ConstraintsTest do
55
alias Ecto.Integration.PoolRepo
66

77
defmodule CustomConstraintHandler do
8+
@behaviour Ecto.Adapters.SQL.Constraint
9+
810
@quotes ~w(" ' `)
911

12+
@impl Ecto.Adapters.SQL.Constraint
1013
# An example of a custom handler a user might write
1114
def to_constraints(%MyXQL.Error{mysql: %{name: :ER_SIGNAL_EXCEPTION}, message: message}, opts) do
1215
# Assumes this is the only use-case of `ER_SIGNAL_EXCEPTION` the user has implemented custom errors for
@@ -194,6 +197,7 @@ defmodule Ecto.Integration.ConstraintsTest do
194197
assert is_integer(result.id)
195198
end
196199

200+
@tag :constraint_handler
197201
test "custom handled constraint" do
198202
changeset = Ecto.Changeset.change(%Constraint{}, from: 0, to: 10)
199203
{:ok, item} = PoolRepo.insert(changeset)

lib/ecto/adapters/myxql/connection.ex

+3-40
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ if Code.ensure_loaded?(MyXQL) do
55

66
@behaviour Ecto.Adapters.SQL.Connection
77

8+
@impl true
9+
defdelegate to_constraints(exception, options), to: Ecto.Adapters.MyXQL.Constraint
10+
811
## Connection
912

1013
@impl true
@@ -56,46 +59,6 @@ if Code.ensure_loaded?(MyXQL) do
5659
end
5760
end
5861

59-
@quotes ~w(" ' `)
60-
61-
@impl true
62-
def to_constraints(%MyXQL.Error{mysql: %{name: :ER_DUP_ENTRY}, message: message}, opts) do
63-
with [_, quoted] <- :binary.split(message, " for key "),
64-
[_, index | _] <- :binary.split(quoted, @quotes, [:global]) do
65-
[unique: strip_source(index, opts[:source])]
66-
else
67-
_ -> []
68-
end
69-
end
70-
71-
def to_constraints(%MyXQL.Error{mysql: %{name: name}, message: message}, _opts)
72-
when name in [:ER_ROW_IS_REFERENCED_2, :ER_NO_REFERENCED_ROW_2] do
73-
with [_, quoted] <- :binary.split(message, [" CONSTRAINT ", " FOREIGN KEY "]),
74-
[_, index | _] <- :binary.split(quoted, @quotes, [:global]) do
75-
[foreign_key: index]
76-
else
77-
_ -> []
78-
end
79-
end
80-
81-
def to_constraints(
82-
%MyXQL.Error{mysql: %{name: :ER_CHECK_CONSTRAINT_VIOLATED}, message: message},
83-
_opts
84-
) do
85-
with [_, quoted] <- :binary.split(message, ["Check constraint "]),
86-
[_, constraint | _] <- :binary.split(quoted, @quotes, [:global]) do
87-
[check: constraint]
88-
else
89-
_ -> []
90-
end
91-
end
92-
93-
def to_constraints(_, _),
94-
do: []
95-
96-
defp strip_source(name, nil), do: name
97-
defp strip_source(name, source), do: String.trim_leading(name, "#{source}.")
98-
9962
## Query
10063

10164
@parent_as __MODULE__

lib/ecto/adapters/myxql/constraint.ex

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
defmodule Ecto.Adapters.MyXQL.Constraint do
2+
@moduledoc false
3+
4+
@behaviour Ecto.Adapters.SQL.Constraint
5+
6+
@quotes ~w(" ' `)
7+
8+
@impl true
9+
def to_constraints(%MyXQL.Error{mysql: %{name: :ER_DUP_ENTRY}, message: message}, opts) do
10+
with [_, quoted] <- :binary.split(message, " for key "),
11+
[_, index | _] <- :binary.split(quoted, @quotes, [:global]) do
12+
[unique: strip_source(index, opts[:source])]
13+
else
14+
_ -> []
15+
end
16+
end
17+
18+
def to_constraints(%MyXQL.Error{mysql: %{name: name}, message: message}, _opts)
19+
when name in [:ER_ROW_IS_REFERENCED_2, :ER_NO_REFERENCED_ROW_2] do
20+
with [_, quoted] <- :binary.split(message, [" CONSTRAINT ", " FOREIGN KEY "]),
21+
[_, index | _] <- :binary.split(quoted, @quotes, [:global]) do
22+
[foreign_key: index]
23+
else
24+
_ -> []
25+
end
26+
end
27+
28+
def to_constraints(
29+
%MyXQL.Error{mysql: %{name: :ER_CHECK_CONSTRAINT_VIOLATED}, message: message},
30+
_opts
31+
) do
32+
with [_, quoted] <- :binary.split(message, ["Check constraint "]),
33+
[_, constraint | _] <- :binary.split(quoted, @quotes, [:global]) do
34+
[check: constraint]
35+
else
36+
_ -> []
37+
end
38+
end
39+
40+
def to_constraints(_, _),
41+
do: []
42+
43+
defp strip_source(name, nil), do: name
44+
defp strip_source(name, source), do: String.trim_leading(name, "#{source}.")
45+
end

0 commit comments

Comments
 (0)