2016-12-21 5 views
0

Мне нужно реализовать следующий запрос с помощью Ecto, однако он не компилируется, говоря, что оператор подзапроса не является допустимым выражением.Предоставление подзапроса в параметрах запроса

query = from p in Passphrase, 
     left_join: pi in PassphraseInvalidation, on: p.id == pi.target_passphrase_id, 
     join: u in User, on: p.user_id == u.id, 
     where: p.passkey == ^passkey and 
       is_nil(pi.inserted_at) and 
       p.inserted_at > ago(5, "month") and 
       p.inserted_at > subquery(from pr in PasswordReset, 
             where: pr.user_id == u.id, 
             select: max(pr.inserted_at)), 
     select: {u, p} 

user = Repo.one!(query) 

(Ecto.Query.CompileError) подзапрос (из (пр в PasswordReset, где: pr.user_id() ==^u.id(), выберите: макс (pr.inserted_at()))) не является допустимым выражением запроса.

Эквивалент PgSQL запрос будет что-то вроде:

SELECT u.*, p.* 
FROM passphrases p 
LEFT OUTER JOIN passphrase_invalidations pi ON p.id = pi.target_passphrase_id 
INNER JOIN users u ON p.user_id = u.id 
WHERE p.passkey = '/* some passkey */' AND 
     pi.inserted_at IS NULL AND 
     u.id = 2 AND 
     p.inserted_at > (SELECT max(pr.inserted_at) 
         FROM password_resets pr 
         WHERE pr.user_id = u.id) 

Есть ли способ осуществить это, или я что-то отсутствует?

+0

https://hexdocs.pm/ecto/Ecto.Query.html#subquery/1 говорит «подзапросы в настоящее время поддерживается только в поля 'from' и' join'. поэтому похоже, что это невозможно в подзапросах прямо сейчас. – Dogbert

+0

@Dogbert, что бы вы сказали об этом, мне нужно предоставить информацию о типе в запросе. Могу ли я использовать 'фрагмент/1' сделать эту работу? – Leviathlon

+1

Как насчет фрагмента p.inserted_at> ("(SELECT max (pr.inserted_at) FROM password_resets pr WHERE pr.user_id = u.id)") '? – Dogbert

ответ

2

По Ecto 2.1.0, согласно https://hexdocs.pm/ecto/Ecto.Query.html#subquery/1, подзапросы не может быть использование в where:

подзапросов в настоящее время поддерживается только в from и join полей.

Вы можете использовать fragment и поставить весь подзапрос в нем на данный момент:

p.inserted_at > fragment("(SELECT max(pr.inserted_at) FROM password_resets pr WHERE pr.user_id = u.id)") 
Смежные вопросы