Ecto schema/db mismatch?

Hello, I have not done much elixir in the last few years, and I wanted to get back into the groove.

I have the following error:

* (DBConnection.EncodeError) Postgrex expected an integer in -9223372036854775808..9223372036854775807, got "order-123". Please make sure the value you are passing matches the definition in your table or in your query or convert the value accordingly.

The error seems to indicate a mismatch between my ecto schema and the actual db. But unless I going blind that’s not the case. I’ll paste my schema, migration and repo bellow. And also I checked my DB using DBeaver and my id column is of type varchar(255) as expected.

Any help to point me in the right direction is more than welcome.

Here is my schema:

defmodule ShopCore.Orders.OrderSchema do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :string, autogenerate: false}
  schema "orders" do
    field :status, :string
    field :line_items, {:array, :map}, default: []
    field :total_price, :integer

    timestamps()
  end

  def changeset(order, attrs) do
    order
    |> cast(attrs, [:id, :status, :line_items, :total_price])
    |> validate_required([:id, :status])
  end
end

Here is my db migration creating the table in question:

defmodule ShopCore.Repo.Migrations.CreateOrders do
  use Ecto.Migration

  def change do
    create table(:orders, primary_key: false) do
      add :id, :string, primary_key: true
      add :status, :string
      add :line_items, {:array, :map}, default: []

      timestamps()
    end
  end
end

And this is my repository:

defmodule ShopCore.Orders.OrderRepo do
  alias ShopCore.Orders.OrderSchema
  alias ShopCore.Repo

  def save_order(%{id: id, status: status, lines: lines} = order) do
    line_maps = Enum.map(lines, fn l ->
      %{
        product_id: l.product_id,
        quantity: l.quantity,
        unit_price: l.unit_price
      }
    end)

    total = ShopCore.Orders.Order.total_price(order)

    IO.inspect(OrderSchema.__schema__(:primary_key), label: "Primary Key Type") #Primary Key Type: [:id]
    IO.inspect(OrderSchema.__schema__(:type, :id), label: "ID field type")                 #ID field type: :string
    IO.inspect(OrderSchema.__schema__(:type, :id), label: "Param ID type")             #Param ID type: :string
    %OrderSchema{}
    |> OrderSchema.changeset(%{id: id, status: Atom.to_string(status), line_items: line_maps, total_price: total})
    |> Repo.insert()
  end

  def find_by_id(id) do
    IO.inspect(OrderSchema.__schema__(:primary_key), label: "Primary Key Type")
    IO.inspect(OrderSchema.__schema__(:type, :id), label: "ID field type")
    with %OrderSchema{} = record <- Repo.get_by(OrderSchema, id: id) do
        domain_order = %ShopCore.Orders.Order{
          id: record.id,
          status: String.to_existing_atom(record.status),
          lines: Enum.map(record.line_items, fn %{"product_id" => pid, "quantity" => qty, "unit_price" => price} ->
            %ShopCore.Orders.OrderLine{product_id: pid, quantity: qty, unit_price: price}
          end)
        }

        {:ok, domain_order}
      else
      nil ->
        {:error, :not_found}
    end
  end

end
1 Like

Try removing the :id from the cast function call?