Project

General

Profile

« Previous | Next » 

Revision 13989

Support for accent insensitive search with PostgreSQL (#18801).

If the unaccent extension is installed, the search engine will use it in order to do accent insensitive search.

View differences:

trunk/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb
159 159
          private :search_tokens_condition
160 160

  
161 161
          def search_token_match_statement(column, value='?')
162
            case connection.adapter_name
163
            when /postgresql/i
164
              "#{column} ILIKE #{value}"
162
            if Redmine::Database.postgresql?
163
              if Redmine::Database.postgresql_unaccent?
164
                "unaccent(#{column}) ILIKE unaccent(#{value})"
165
              else
166
                "#{column} ILIKE #{value}"
167
              end
165 168
            else
166 169
              "#{column} LIKE #{value}"
167 170
            end
trunk/lib/redmine/database.rb
1
# Redmine - project management software
2
# Copyright (C) 2006-2015  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
module Redmine
19
  # Helper module to get information about the Redmine database
20
  module Database
21
    class << self
22
      # Returns true if the database is PostgreSQL
23
      def postgresql?
24
        (ActiveRecord::Base.connection.adapter_name =~ /postgresql/i).present?
25
      end
26

  
27
      # Returns the PostgreSQL version or nil if another DBMS is used
28
      def postgresql_version
29
        postgresql? ? ActiveRecord::Base.connection.send(:postgresql_version) : nil
30
      end
31

  
32
      # Returns true if the database is a PostgreSQL >=9.0 database with the unaccent extension installed
33
      def postgresql_unaccent?
34
        if postgresql?
35
          return @postgresql_unaccent unless @postgresql_unaccent.nil?
36
          begin
37
            sql = "SELECT name FROM pg_available_extensions WHERE installed_version IS NOT NULL and name = 'unaccent'"
38
            @postgresql_unaccent = postgresql_version >= 90000 && ActiveRecord::Base.connection.select_value(sql).present?
39
          rescue
40
            false
41
          end
42
        else
43
          false
44
        end
45
      end
46

  
47
      # Resets database information
48
      def reset
49
        @postgresql_unaccent = nil
50
      end
51
    end
52
  end
53
end
0 54

  
trunk/test/test_helper.rb
169 169
    ActiveRecord::Base.connection.adapter_name =~ /mysql/i
170 170
  end
171 171

  
172
  def postgresql?
173
    ActiveRecord::Base.connection.adapter_name =~ /postgresql/i
174
  end
175

  
172 176
  def assert_save(object)
173 177
    saved = object.save
174 178
    message = "#{object.class} could not be saved"
trunk/test/unit/search_test.rb
171 171
    end
172 172
  end
173 173

  
174
  def test_search_should_be_case_and_accent_insensitive_with_postgresql_and_noaccent_extension
175
    if postgresql?
176
      skip unless Redmine::Database.postgresql_version >= 90000
177
      # Extension will be rollbacked with the test transaction
178
      ActiveRecord::Base.connection.execute("CREATE EXTENSION IF NOT EXISTS unaccent")
179
      Redmine::Database.reset
180
      assert Redmine::Database.postgresql_unaccent?
181

  
182
      issue1 = Issue.generate!(:subject => "OO")
183
      issue2 = Issue.generate!(:subject => "oo")
184
  
185
      r = Issue.search_results('ÖÖ')
186
      assert_include issue1, r
187
      assert_include issue2, r
188
    end
189
  ensure
190
    Redmine::Database.reset
191
  end
192

  
174 193
  private
175 194

  
176 195
  def remove_permission(role, permission)

Also available in: Unified diff