#elixir #ecto
#elixir #ecto
Вопрос:
Я хотел бы получить lock
using FOR UPDATE OF table_name
. По сравнению с FOR UPDATE
, FOR UPDATE OF
блокирует только строку в указанной таблице, а объединенные строки не блокируются. Однако, когда я пытаюсь сделать это с помощью 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")
Использование псевдонима не похоже на правильный способ сделать это. Есть ли какой-либо другой способ заставить ее работать?
Ответ №1:
По состоянию на Ecto v3
нет способа передать параметризованное значение в Query.lock
. Он принимает только двоичные файлы.
[Именованные привязки] также не будут работать, потому что Ecto
внутренне генерирует псевдонимы по своему усмотрению.
Следующий подход был бы ближайшим, но он также не работает, потому что Ecto.Query.lock/2
не допускает интерполяции.
Используйте Ecto.Query.API.fragment
, который имеет возможность интерполяции, с синтаксисом запроса ключевого слова. Что-то вроде:
from c in Call,
join: ..., # custom methods
lock: fragment("FOR UPDATE OF ?", c)
Комментарии:
1. Это выдает следующую ошибку:
fragment("FOR UPDATE OF ?", c) is not a valid lock. For security reasons, a lock must always be a literal string
2. Черт возьми, действительно они разрешают там только двоичные файлы. Тогда вы могли бы попробовать именованную привязку . Дайте мне знать, если это удастся, я либо обновлю ответ, либо удалю его.
3. К сожалению, это тоже не работает. Похоже, что Ecto использует эти псевдонимы внутренне, но для фактического SQL-запроса он по-прежнему генерирует новые псевдонимы .
4. Да, и генератор является частным. Извините, что говорю это, но похоже, что вам следует остановиться на последнем средстве:
"c0"
жестко закодированном. Я удалю ответ.5. Или добавьте обновление к ответу, что в настоящее время нет способа сделать это, начиная с версии Ecto версии 3.
Ответ №2:
Обратите внимание, похоже, что теперь вы можете использовать фрагмент для интерполяции имени таблицы в, см. https://github.com/elixir-ecto/ecto_sql/pull/189 . Таким образом, решение от Алексея теперь должно работать:
from c in Call,
join: ..., # custom methods
lock: fragment("FOR UPDATE OF ?", c)