From b1b98874a5f00d8c2011841809d1fa29e0abca65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20B=C4=82LTEANU?= Date: Sat, 28 Feb 2026 13:10:34 +0700 Subject: [PATCH 2/3] Add an index to users login to speed up find user by login and for databases which are case-insensitive by default, search in the existing results. --- app/models/user.rb | 10 ++++++++-- db/migrate/20260225170822_add_index_to_users_login.rb | 9 +++++++++ lib/redmine/database.rb | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20260225170822_add_index_to_users_login.rb diff --git a/app/models/user.rb b/app/models/user.rb index bec279eb2..4bb8c6856 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -546,11 +546,17 @@ class User < Principal def self.find_by_login(login) login = Redmine::CodesetUtil.replace_invalid_utf8(login.to_s) if login.present? + users = where(:login => login) # First look for an exact match - user = where(:login => login).detect {|u| u.login == login} + user = users.detect {|u| u.login == login} unless user # Fail over to case-insensitive if none was found - user = find_by("LOWER(login) = ?", login.downcase) + if Redmine::Database.mysql? || Redmine::Database.sqlserver? + # MySQL and SQLServer are case-insensitive by default, we can search in the existing results + user = users.detect {|u| u.login.casecmp?(login)} + else + user = find_by("LOWER(login) = ?", login.downcase) + end end user end diff --git a/db/migrate/20260225170822_add_index_to_users_login.rb b/db/migrate/20260225170822_add_index_to_users_login.rb new file mode 100644 index 000000000..4c6968fdb --- /dev/null +++ b/db/migrate/20260225170822_add_index_to_users_login.rb @@ -0,0 +1,9 @@ +class AddIndexToUsersLogin < ActiveRecord::Migration[8.1] + def up + add_index :users, :login + end + + def down + remove_index :users, :login + end +end diff --git a/lib/redmine/database.rb b/lib/redmine/database.rb index 13c92b8a4..7c95d5da3 100644 --- a/lib/redmine/database.rb +++ b/lib/redmine/database.rb @@ -65,6 +65,10 @@ module Redmine mysql? ? ActiveRecord::Base.connection.select_value("SELECT VERSION()") : nil end + def sqlserver? + /sqlserver/i.match?(ActiveRecord::Base.connection.adapter_name) + end + # Returns a SQL statement for case/accent (if possible) insensitive match def like(left, right, options={}) neg = (options[:match] == false ? 'NOT ' : '') -- 2.50.1 (Apple Git-155)