# HG changeset patch # Parent 0f20192530e87d6fa75b9ce496352b57e6e52429 # User Toshi MARUYAMA (#24013) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -170,7 +170,7 @@ class ApplicationController < ActionCont if User.current.logged? cookies.delete(autologin_cookie_name) Token.where(["user_id = ? AND action = ?", User.current.id, 'autologin']).delete_all - Token.where(["user_id = ? AND action = ? AND value = ?", User.current.id, 'session', session[:tk]]).delete_all + Token.where(["user_id = ? AND action = ?", User.current.id, 'session']).where(:value => session[:tk]).delete_all self.logged_user = nil end end diff --git a/app/controllers/versions_controller.rb b/app/controllers/versions_controller.rb --- a/app/controllers/versions_controller.rb +++ b/app/controllers/versions_controller.rb @@ -50,7 +50,7 @@ class VersionsController < ApplicationCo includes(:project, :tracker). preload(:status, :priority, :fixed_version). where(:tracker_id => @selected_tracker_ids, :project_id => project_ids, :fixed_version_id => @versions.map(&:id)). - order("#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id") + order("#{Project.table_name}.lft, #{Tracker.table_name}.#{'position'.quote_column_name}, #{Issue.table_name}.id") @issues_by_version = issues.group_by(&:fixed_version) end @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?} @@ -67,7 +67,7 @@ class VersionsController < ApplicationCo @issues = @version.fixed_issues.visible. includes(:status, :tracker, :priority). preload(:project). - reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id"). + reorder("#{Issue.table_name}.id"). to_a } format.api diff --git a/app/models/project.rb b/app/models/project.rb --- a/app/models/project.rb +++ b/app/models/project.rb @@ -44,14 +44,14 @@ class Project < ActiveRecord::Base has_many :documents, :dependent => :destroy has_many :news, lambda {includes(:author)}, :dependent => :destroy has_many :issue_categories, lambda {order("#{IssueCategory.table_name}.name")}, :dependent => :delete_all - has_many :boards, lambda {order("position ASC")}, :dependent => :destroy + has_many :boards, lambda { order(:position) }, :dependent => :destroy has_one :repository, lambda {where(["is_default = ?", true])} has_many :repositories, :dependent => :destroy has_many :changesets, :through => :repository has_one :wiki, :dependent => :destroy # Custom field for the project issues has_and_belongs_to_many :issue_custom_fields, - lambda {order("#{CustomField.table_name}.position")}, + lambda { order("#{CustomField.table_name}.#{'position'.quote_column_name}") }, :class_name => 'IssueCustomField', :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :association_foreign_key => 'custom_field_id' diff --git a/app/models/query.rb b/app/models/query.rb --- a/app/models/query.rb +++ b/app/models/query.rb @@ -824,7 +824,7 @@ class Query < ActiveRecord::Base def sql_for_custom_field(field, operator, value, custom_field_id) db_table = CustomValue.table_name - db_field = 'value' + db_field = 'value'.quote_column_name filter = @available_filters[field] return nil unless filter if filter[:field].format.target_class && filter[:field].format.target_class <= User @@ -869,7 +869,7 @@ class Query < ActiveRecord::Base int_values = value.first.to_s.scan(/[+-]?\d+/).map(&:to_i).join(",") if int_values.present? if is_custom_filter - sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) IN (#{int_values}))" + sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) IN (#{int_values}))" else sql = "#{db_table}.#{db_field} IN (#{int_values})" end @@ -878,7 +878,7 @@ class Query < ActiveRecord::Base end when :float if is_custom_filter - sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5})" + sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5})" else sql = "#{db_table}.#{db_field} BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5}" end @@ -907,7 +907,7 @@ class Query < ActiveRecord::Base sql = date_clause(db_table, db_field, parse_date(value.first), nil, is_custom_filter) else if is_custom_filter - sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) >= #{value.first.to_f})" + sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) >= #{value.first.to_f})" else sql = "#{db_table}.#{db_field} >= #{value.first.to_f}" end @@ -917,7 +917,7 @@ class Query < ActiveRecord::Base sql = date_clause(db_table, db_field, nil, parse_date(value.first), is_custom_filter) else if is_custom_filter - sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) <= #{value.first.to_f})" + sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) <= #{value.first.to_f})" else sql = "#{db_table}.#{db_field} <= #{value.first.to_f}" end @@ -927,7 +927,7 @@ class Query < ActiveRecord::Base sql = date_clause(db_table, db_field, parse_date(value[0]), parse_date(value[1]), is_custom_filter) else if is_custom_filter - sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) BETWEEN #{value[0].to_f} AND #{value[1].to_f})" + sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(18,3)) BETWEEN #{value[0].to_f} AND #{value[1].to_f})" else sql = "#{db_table}.#{db_field} BETWEEN #{value[0].to_f} AND #{value[1].to_f}" end @@ -1079,7 +1079,11 @@ class Query < ActiveRecord::Base s = [] if from if from.is_a?(Date) - from = date_for_user_time_zone(from.year, from.month, from.day).yesterday.end_of_day + if Redmine::Database.firebird? + from = date_for_user_time_zone(from.year, from.month, from.day).yesterday.end_of_day.to_date + else + from = date_for_user_time_zone(from.year, from.month, from.day).yesterday.end_of_day + end else from = from - 1 # second end @@ -1090,7 +1094,11 @@ class Query < ActiveRecord::Base end if to if to.is_a?(Date) - to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day + if Redmine::Database.firebird? + to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day.to_date + else + to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day + end end if self.class.default_timezone == :utc to = to.utc diff --git a/app/models/repository.rb b/app/models/repository.rb --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -422,12 +422,12 @@ class Repository < ActiveRecord::Base # Notes: # - this hash honnors the users mapping defined for the repository def stats_by_author - commits = Changeset.where("repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id") + commits = Changeset.where("repository_id = ?", id).select("committer, user_id, count(*) as commit_count").group("committer, user_id") #TODO: restore ordering ; this line probably never worked #commits.to_a.sort! {|x, y| x.last <=> y.last} - changes = Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id") + changes = Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", id).select("committer, user_id, count(*) as commit_count").group("committer, user_id") user_ids = changesets.map(&:user_id).compact.uniq authors_names = User.where(:id => user_ids).inject({}) do |memo, user| @@ -442,9 +442,9 @@ class Repository < ActiveRecord::Base end hash[mapped_name] ||= { :commits_count => 0, :changes_count => 0 } if element.is_a?(Changeset) - hash[mapped_name][:commits_count] += element.count.to_i + hash[mapped_name][:commits_count] += element.commit_count.to_i else - hash[mapped_name][:changes_count] += element.count.to_i + hash[mapped_name][:changes_count] += element.commit_count.to_i end hash end diff --git a/app/models/user.rb b/app/models/user.rb --- a/app/models/user.rb +++ b/app/models/user.rb @@ -684,7 +684,7 @@ class User < Principal # Returns true if the user is allowed to delete the user's own account def own_account_deletable? Setting.unsubscribe? && - (!admin? || User.active.where("admin = ? AND id <> ?", true, id).exists?) + (!admin? || User.active.where("id <> ?", id).where(:admin => true).exists?) end safe_attributes 'firstname', @@ -821,8 +821,9 @@ class User < Principal where(["property = 'attr' AND prop_key = 'assigned_to_id' AND old_value = ?", id.to_s]). update_all(['old_value = ?', substitute.id.to_s]) JournalDetail. - where(["property = 'attr' AND prop_key = 'assigned_to_id' AND value = ?", id.to_s]). - update_all(['value = ?', substitute.id.to_s]) + where(["property = 'attr' AND prop_key = 'assigned_to_id'"]). + where(:value => id.to_s). + update_all(:value => substitute.id.to_s) Message.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) News.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) # Remove private queries and keep public ones diff --git a/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb b/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb --- a/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb +++ b/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb @@ -27,7 +27,7 @@ module Redmine return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods) cattr_accessor :customizable_options self.customizable_options = options - has_many :custom_values, lambda {includes(:custom_field).order("#{CustomField.table_name}.position")}, + has_many :custom_values, lambda {joins(:custom_field).merge(CustomField.order(:position))}, :as => :customized, :dependent => :delete_all, :validate => false diff --git a/lib/plugins/open_id_authentication/lib/open_id_authentication/association.rb b/lib/plugins/open_id_authentication/lib/open_id_authentication/association.rb --- a/lib/plugins/open_id_authentication/lib/open_id_authentication/association.rb +++ b/lib/plugins/open_id_authentication/lib/open_id_authentication/association.rb @@ -1,6 +1,6 @@ module OpenIdAuthentication class Association < ActiveRecord::Base - self.table_name = :open_id_authentication_associations + self.table_name = :open_id_auth_associations def from_record OpenID::Association.new(handle, secret, issued, lifetime, assoc_type) diff --git a/lib/redmine/database.rb b/lib/redmine/database.rb --- a/lib/redmine/database.rb +++ b/lib/redmine/database.rb @@ -49,6 +49,11 @@ module Redmine (ActiveRecord::Base.connection.adapter_name =~ /mysql/i).present? end + # Returns +true+ if the database is Firebird or RedDatabase + def firebird? + (ActiveRecord::Base.connection.adapter_name =~ /fb/i).present? + end + # Returns a SQL statement for case/accent (if possible) insensitive match def like(left, right, options={}) neg = (options[:match] == false ? 'NOT ' : '') diff --git a/lib/redmine/field_format.rb b/lib/redmine/field_format.rb --- a/lib/redmine/field_format.rb +++ b/lib/redmine/field_format.rb @@ -294,7 +294,7 @@ module Redmine # Returns nil if the custom field can not be used for sorting. def order_statement(custom_field) # COALESCE is here to make sure that blank and NULL values are sorted equally - "COALESCE(#{join_alias custom_field}.value, '')" + "COALESCE(#{join_alias custom_field}.#{value_column}, '')" end # Returns a GROUP BY clause that can used to group by custom value @@ -312,7 +312,7 @@ module Redmine " AND #{alias_name}.customized_id = #{custom_field.class.customized_class.table_name}.id" + " AND #{alias_name}.custom_field_id = #{custom_field.id}" + " AND (#{custom_field.visibility_by_project_condition})" + - " AND #{alias_name}.value <> ''" + + " AND #{alias_name}.#{value_column} <> ''" + " AND #{alias_name}.id = (SELECT max(#{alias_name}_2.id) FROM #{CustomValue.table_name} #{alias_name}_2" + " WHERE #{alias_name}_2.customized_type = #{alias_name}.customized_type" + " AND #{alias_name}_2.customized_id = #{alias_name}.customized_id" + @@ -322,6 +322,10 @@ module Redmine def join_alias(custom_field) "cf_#{custom_field.id}" end + + def value_column + 'value'.quote_column_name + end protected :join_alias end @@ -431,7 +435,7 @@ module Redmine # Make the database cast values into numeric # Postgresql will raise an error if a value can not be casted! # CustomValue validations should ensure that it doesn't occur - "CAST(CASE #{join_alias custom_field}.value WHEN '' THEN '0' ELSE #{join_alias custom_field}.value END AS decimal(30,3))" + "CAST(CASE #{join_alias custom_field}.#{value_column} WHEN '' THEN '0' ELSE #{join_alias custom_field}.#{value_column} END AS decimal(18,3))" end # Returns totals for the given scope @@ -439,7 +443,7 @@ module Redmine scope.joins(:custom_values). where(:custom_values => {:custom_field_id => custom_field.id}). where.not(:custom_values => {:value => ''}). - sum("CAST(#{CustomValue.table_name}.value AS decimal(30,3))") + sum("CAST(#{CustomValue.table_name}.#{value_column} AS decimal(18,3))") end def cast_total_value(custom_field, value) @@ -719,7 +723,7 @@ module Redmine end def group_statement(custom_field) - "COALESCE(#{join_alias custom_field}.value, '')" + "COALESCE(#{join_alias custom_field}.#{value_column}, '')" end def join_for_order_statement(custom_field) @@ -730,13 +734,13 @@ module Redmine " AND #{alias_name}.customized_id = #{custom_field.class.customized_class.table_name}.id" + " AND #{alias_name}.custom_field_id = #{custom_field.id}" + " AND (#{custom_field.visibility_by_project_condition})" + - " AND #{alias_name}.value <> ''" + + " AND #{alias_name}.#{value_column} <> ''" + " AND #{alias_name}.id = (SELECT max(#{alias_name}_2.id) FROM #{CustomValue.table_name} #{alias_name}_2" + " WHERE #{alias_name}_2.customized_type = #{alias_name}.customized_type" + " AND #{alias_name}_2.customized_id = #{alias_name}.customized_id" + " AND #{alias_name}_2.custom_field_id = #{alias_name}.custom_field_id)" + " LEFT OUTER JOIN #{target_class.table_name} #{value_join_alias custom_field}" + - " ON CAST(CASE #{alias_name}.value WHEN '' THEN '0' ELSE #{alias_name}.value END AS decimal(30,0)) = #{value_join_alias custom_field}.id" + " ON CAST(CASE #{alias_name}.#{value_column} WHEN '' THEN '0' ELSE #{alias_name}.#{value_column} END AS decimal(18,0)) = #{value_join_alias custom_field}.id" end def value_join_alias(custom_field) diff --git a/lib/tasks/migrate_from_mantis.rake b/lib/tasks/migrate_from_mantis.rake --- a/lib/tasks/migrate_from_mantis.rake +++ b/lib/tasks/migrate_from_mantis.rake @@ -52,7 +52,7 @@ task :migrate_from_mantis => :environmen TRACKER_BUG = Tracker.find_by_position(1) TRACKER_FEATURE = Tracker.find_by_position(2) - roles = Role.where(:builtin => 0).order('position ASC').all + roles = Role.where(:builtin => 0).order(:position).all manager_role = roles[0] developer_role = roles[1] DEFAULT_ROLE = roles.last diff --git a/lib/tasks/migrate_from_trac.rake b/lib/tasks/migrate_from_trac.rake --- a/lib/tasks/migrate_from_trac.rake +++ b/lib/tasks/migrate_from_trac.rake @@ -60,7 +60,7 @@ namespace :redmine do 'patch' =>TRACKER_FEATURE } - roles = Role.where(:builtin => 0).order('position ASC').all + roles = Role.where(:builtin => 0).order(:position).all manager_role = roles[0] developer_role = roles[1] DEFAULT_ROLE = roles.last diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -1051,7 +1051,7 @@ class UserTest < ActiveSupport::TestCase end def test_own_account_deletable_should_be_false_for_a_single_admin - User.where(["admin = ? AND id <> ?", true, 1]).delete_all + User.where(["id <> ?", 1]).where(:admin => true).delete_all with_settings :unsubscribe => '1' do assert_equal false, User.find(1).own_account_deletable?