[28348] Coalesce values for contains filter

https://community.openproject.com/wp/28348
pull/6564/head
Oliver Günther 6 years ago
parent f1b47c2302
commit 1c7626efe8
No known key found for this signature in database
GPG Key ID: A3A8BDAD7C0C552C
  1. 2
      app/models/queries/operators/contains.rb
  2. 2
      app/models/queries/operators/not_contains.rb
  3. 97
      spec/models/queries/work_packages/filter/custom_fields/contains_text_custom_field_filter_spec.rb
  4. 0
      spec/models/queries/work_packages/filter/custom_fields/custom_field_filter_spec.rb
  5. 4
      spec_legacy/unit/query_spec.rb

@ -33,7 +33,7 @@ module Queries::Operators
set_symbol '~' set_symbol '~'
def self.sql_for_field(values, db_table, db_field) def self.sql_for_field(values, db_table, db_field)
"LOWER(#{db_table}.#{db_field}) LIKE " + "COALESCE(LOWER(#{db_table}.#{db_field}), '') LIKE " +
"'%#{connection.quote_string(values.first.to_s.downcase)}%'" "'%#{connection.quote_string(values.first.to_s.downcase)}%'"
end end
end end

@ -33,7 +33,7 @@ module Queries::Operators
set_symbol '!~' set_symbol '!~'
def self.sql_for_field(values, db_table, db_field) def self.sql_for_field(values, db_table, db_field)
"LOWER(#{db_table}.#{db_field}) NOT LIKE " + "COALESCE(LOWER(#{db_table}.#{db_field}), '') NOT LIKE " +
"'%#{connection.quote_string(values.first.to_s.downcase)}%'" "'%#{connection.quote_string(values.first.to_s.downcase)}%'"
end end
end end

@ -0,0 +1,97 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe Queries::WorkPackages::Filter::CustomFieldFilter,
'with contains filter (Regression test #28348)',
type: :model do
let(:cf_accessor) { "cf_#{custom_field.id}" }
let(:query) { FactoryBot.build_stubbed(:query, project: project) }
let(:instance) do
described_class.create!(name: cf_accessor, operator: operator, values: %w(foo), context: query)
end
let(:project) do
FactoryBot.create :project,
types: [type],
work_package_custom_fields: [custom_field]
end
let(:custom_field) do
FactoryBot.create(:text_issue_custom_field, name: 'LongText')
end
let(:type) { FactoryBot.create(:type_standard, custom_fields: [custom_field]) }
let!(:wp_contains) do
FactoryBot.create :work_package,
type: type,
project: project,
custom_values: { custom_field.id => 'foo' }
end
let!(:wp_not_contains) do
FactoryBot.create :work_package,
type: type,
project: project,
custom_values: { custom_field.id => 'bar' }
end
let!(:wp_empty) do
FactoryBot.create :work_package,
type: type,
project: project,
custom_values: { custom_field.id => '' }
end
let!(:wp_nil) do
FactoryBot.create :work_package,
type: type,
project: project,
custom_values: { custom_field.id => nil }
end
subject { WorkPackage.where(instance.where) }
describe 'contains' do
let(:operator) { '~' }
it 'returns the one matching work package' do
is_expected
.to match_array [wp_contains]
end
end
describe 'not contains' do
let(:operator) { '!~' }
it 'returns the three non-matching work package' do
is_expected
.to match_array [wp_not_contains, wp_empty, wp_nil]
end
end
end

@ -191,7 +191,7 @@ describe Query, type: :model do
it 'should operator contains' do it 'should operator contains' do
query = Query.new(project: Project.find(1), name: '_') query = Query.new(project: Project.find(1), name: '_')
query.add_filter('subject', '~', ['uNable']) query.add_filter('subject', '~', ['uNable'])
assert query.statement.include?("LOWER(#{WorkPackage.table_name}.subject) LIKE '%unable%'") assert query.statement.include?("COALESCE(LOWER(#{WorkPackage.table_name}.subject), '') LIKE '%unable%'")
result = find_issues_with_query(query) result = find_issues_with_query(query)
assert result.empty? assert result.empty?
result.each { |issue| assert issue.subject.downcase.include?('unable') } result.each { |issue| assert issue.subject.downcase.include?('unable') }
@ -200,7 +200,7 @@ describe Query, type: :model do
it 'should operator does not contains' do it 'should operator does not contains' do
query = Query.new(project: Project.find(1), name: '_') query = Query.new(project: Project.find(1), name: '_')
query.add_filter('subject', '!~', ['uNable']) query.add_filter('subject', '!~', ['uNable'])
assert query.statement.include?("LOWER(#{WorkPackage.table_name}.subject) NOT LIKE '%unable%'") assert query.statement.include?("COALESCE(LOWER(#{WorkPackage.table_name}.subject), '') NOT LIKE '%unable%'")
find_issues_with_query(query) find_issues_with_query(query)
end end

Loading…
Cancel
Save