使用 Ecto/Elixir 锁定行 "FOR UPDATE OF" 具体 table

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

我想使用 FOR UPDATE OF table_name 获得一个 lock。与FOR UPDATE相比,FOR UPDATE OF只锁定指定table中的行,并没有阻塞连接的行。但是,当我尝试使用以下代码片段对 Ecto 执行此操作时,它失败了。

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

原因是 Ecto 使用 calls 的别名,例如 c0,这意味着我也必须在锁定表达式中使用别名才能使其正常工作。

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

使用别名看起来不是一个正确的方法。有没有其他方法让它工作?

Ecto v3 开始,无法将参数化值传递给 Query.lock。它接受 binaries only.

[命名绑定] 也不起作用,因为 Ecto 在内部 generates aliases as it wants


以下方法是最接近的方法,但它也不起作用,因为 Ecto.Query.lock/2 不允许插值。

使用Ecto.Query.API.fragment,具有插值能力,关键字查询语法。有点像:

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

请注意,您现在可以使用片段插入 table 名称,请参阅 https://github.com/elixir-ecto/ecto_sql/pull/189。所以 Aleksei 的解决方案现在应该可以工作了:

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