Unexpected result in mid-multi query

Hey,

Here is my little multi:

    case attrs do
      %{"default" => "true"} ->
        Multi.new()
        |> Multi.update_all(:set_default_to_false, VATType, set: [default: false])

      _ ->
        Multi.new()
    end
    |> Multi.update(:update_vat_type, VATType.changeset(vat_type, attrs))
    |> Multi.run(:no_default, fn repo, _ ->
      IO.inspect(get_by_id(vat_type.id))

      case repo.get_by(VATType, default: true) do
        %VATType{} = _vat_type ->
          {:ok, :present}

        x ->
          IO.inspect(x)
          {:error, VATType.changeset_error(:default, "no default", vat_type)}
      end
    end)
    |> Repo.transaction()

What confuses me is the following:
I update all the items’ default value to false, and then I update the current one as default, to ensure only one is default at any time.
When I get the item to do the check in the run, what state am I getting?
It is not the db, because in the db I am seeing true and here false.
But if I am setting from false to true I am still seeing false here.

Could someone shed some light on this?
The weird behavior happens once my update fails and I retry.

I thought that queries inside the multi return the state inside the multi, is this correct?
With this multi shouldn’t I be getting the result of the single update always?

EDIT:
If I explicitly omit the item in question from the update_all step then it works as expected.

What’s the value in vat_type here? It’s read during the construction of the multi, before the update_all, so if attrs has %{"default" => "true"} but vat_type.default is already true then update_vat_type will be a no-op.

2 Likes

Yes, if I change the update to run and get the vat_type in there, after the update_all it is false and gets updated, instead of no-op.

Thank you