Trying to prevent upset from updating `inserted_at` but fail to do so

I have tried this

    |> Device.changeset(attrs)
    |> Repo.insert(
      on_conflict: {:replace_all_except, [:id, :inserted_at]},
      conflict_target: [:device_id]

But inserted_at is still being updated. I looked into Ecto code and saw this

defp load_changes(changeset, state, types, values, embeds, autogen, adapter, schema_meta) do
    %{data: data, changes: changes} = changeset

    IO.puts("load_changes #{inspect(autogen)}")

    data =
      |> merge_changes(changes)
      |> Map.merge(embeds)
      |> merge_autogen(autogen)
      |> apply_metadata(state, schema_meta)
      |> load_each(values, types, adapter)

    IO.puts("load_changes #{inspect(data)}")

    Map.put(changeset, :data, data)

It seems at the end of the day merge_autogen will still populate inserted_at and updated_at
Am I doing this wrong?

Just to share my findings. It seem the Echo code is doing the right stuff all along. Just that

      on_conflict: {:replace_all_except, [:id, :inserted_at]},
      conflict_target: [:device_id]

is not returning the latest state of the database. We need to include returning: true to have a read after write behaviour

1 Like