Search code examples
elixirecto

Lock row "FOR UPDATE OF" specific table using Ecto/Elixir


I would like to acquire a lock using FOR UPDATE OF table_name. In comparison to FOR UPDATE, FOR UPDATE OF only locks the row in the specified table and the joined rows are not blocked. However, when I try to do it with Ecto using the following snippet it fails.

query =
  Call
  |> join_other_tables() # custom methods
  |> Query.lock("FOR UPDATE OF calls")

The reason is Ecto uses an alias for calls, for example, c0, which means that I also have to use the alias in the lock expression to get it working.

query =
  Call
  |> join_other_tables() # custom methods
  |> Query.lock("FOR UPDATE OF c0")

Using the alias does not look like a proper way to do it. Is there any other way to get it working?


Solution

  • As of Ecto v3 there is no way to pass the parameterized value to Query.lock. It accepts binaries only.

    [Named bindings] won’t work either because Ecto internally generates aliases as it wants.


    The following approach would be the nearest one, but it does not work either because Ecto.Query.lock/2 does not allow interpolation.

    Use Ecto.Query.API.fragment, that has an interpolation ability, with the keyword query syntax. Somewhat like:

    from c in Call,
      join: ..., # custom methods
      lock: fragment("FOR UPDATE OF ?", c)