From a9df714764d6138bf162acd82b780ca82a21864b Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 29 Oct 2015 17:51:49 +0100 Subject: [PATCH] Use a subquery with IDs only for find_by_any_email This further improves performance of User.find_by_any_email and is roughly twice as fast as the previous UNION setup. Thanks again to @dlemstra for suggesting this. --- app/models/user.rb | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 66db70080b7..67fef1c1e6a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -235,15 +235,13 @@ class User < ActiveRecord::Base # Find a User by their primary email or any associated secondary email def find_by_any_email(email) - # Arel doesn't allow for chaining operations on union nodes, thus we have - # to write this query by hand. See the following issue for more info: - # https://github.com/rails/arel/issues/98. - sql = '(SELECT * FROM users WHERE email = :email) - UNION - (SELECT users.* - FROM emails - INNER JOIN users ON users.id = emails.user_id - WHERE emails.email = :email) + sql = 'SELECT * + FROM users + WHERE id IN ( + SELECT id FROM users WHERE email = :email + UNION + SELECT emails.user_id FROM emails WHERE email = :email + ) LIMIT 1;' User.find_by_sql([sql, { email: email }]).first