|
| 1 | +defmodule Ecto.Integration.ConstraintsTest do |
| 2 | + use ExUnit.Case, async: true |
| 3 | + |
| 4 | + import Ecto.Migrator, only: [up: 4] |
| 5 | + alias Ecto.Integration.PoolRepo |
| 6 | + |
| 7 | + defmodule ConstraintMigration do |
| 8 | + use Ecto.Migration |
| 9 | + |
| 10 | + @table table(:constraints_test) |
| 11 | + |
| 12 | + def change do |
| 13 | + create @table do |
| 14 | + add :price, :integer |
| 15 | + add :fromm, :integer |
| 16 | + add :too, :integer, check: %{name: "cannot_overlap", expr: "fromm < too"} |
| 17 | + end |
| 18 | + end |
| 19 | + end |
| 20 | + |
| 21 | + defmodule Constraint do |
| 22 | + use Ecto.Integration.Schema |
| 23 | + |
| 24 | + schema "constraints_test" do |
| 25 | + field :price, :integer |
| 26 | + field :fromm, :integer |
| 27 | + field :too, :integer |
| 28 | + end |
| 29 | + end |
| 30 | + |
| 31 | + @base_migration 2_000_000 |
| 32 | + |
| 33 | + setup_all do |
| 34 | + ExUnit.CaptureLog.capture_log(fn -> |
| 35 | + num = @base_migration + System.unique_integer([:positive]) |
| 36 | + up(PoolRepo, num, ConstraintMigration, log: false) |
| 37 | + end) |
| 38 | + |
| 39 | + :ok |
| 40 | + end |
| 41 | + |
| 42 | + test "check constraint" do |
| 43 | + changeset = Ecto.Changeset.change(%Constraint{}, fromm: 0, too: 10) |
| 44 | + {:ok, _} = PoolRepo.insert(changeset) |
| 45 | + |
| 46 | + non_overlapping_changeset = Ecto.Changeset.change(%Constraint{}, fromm: 11, too: 12) |
| 47 | + {:ok, _} = PoolRepo.insert(non_overlapping_changeset) |
| 48 | + |
| 49 | + overlapping_changeset = Ecto.Changeset.change(%Constraint{}, fromm: 1900, too: 12) |
| 50 | + |
| 51 | + exception = |
| 52 | + assert_raise Ecto.ConstraintError, ~r/constraint error when attempting to insert struct/, fn -> |
| 53 | + PoolRepo.insert(overlapping_changeset) |
| 54 | + end |
| 55 | + assert exception.message =~ "cannot_overlap (check_constraint)" |
| 56 | + assert exception.message =~ "The changeset has not defined any constraint." |
| 57 | + assert exception.message =~ "call `check_constraint/3`" |
| 58 | + |
| 59 | + {:error, changeset} = |
| 60 | + overlapping_changeset |
| 61 | + |> Ecto.Changeset.check_constraint(:fromm, name: :cannot_overlap) |
| 62 | + |> PoolRepo.insert() |
| 63 | + assert changeset.errors == [fromm: {"is invalid", [constraint: :check, constraint_name: "cannot_overlap"]}] |
| 64 | + assert changeset.data.__meta__.state == :built |
| 65 | + end |
| 66 | +end |
0 commit comments