Feature #24013 » Firebird_support_v3.patch
| app/controllers/application_controller.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 170 | 170 |
if User.current.logged? |
| 171 | 171 |
cookies.delete(autologin_cookie_name) |
| 172 | 172 |
Token.where(["user_id = ? AND action = ?", User.current.id, 'autologin']).delete_all |
| 173 |
Token.where(["user_id = ? AND action = ? AND value = ?", User.current.id, 'session', session[:tk]]).delete_all
|
|
| 173 |
Token.where(["user_id = ? AND action = ?", User.current.id, 'session']).where(:value => session[:tk]).delete_all
|
|
| 174 | 174 |
self.logged_user = nil |
| 175 | 175 |
end |
| 176 | 176 |
end |
| app/controllers/versions_controller.rb (revision 7f907885578a7e7baa375054626e5e86f0efef5e) | ||
|---|---|---|
| 50 | 50 |
includes(:project, :tracker). |
| 51 | 51 |
preload(:status, :priority, :fixed_version). |
| 52 | 52 |
where(:tracker_id => @selected_tracker_ids, :project_id => project_ids, :fixed_version_id => @versions.map(&:id)). |
| 53 |
order("#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
|
|
| 53 |
order("#{Project.table_name}.lft, #{Tracker.table_name}.#{'position'.quote_column_name}, #{Issue.table_name}.id")
|
|
| 54 | 54 |
@issues_by_version = issues.group_by(&:fixed_version) |
| 55 | 55 |
end |
| 56 | 56 |
@versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
|
| ... | ... | |
| 67 | 67 |
@issues = @version.fixed_issues.visible. |
| 68 | 68 |
includes(:status, :tracker, :priority). |
| 69 | 69 |
preload(:project). |
| 70 |
reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id").
|
|
| 70 |
reorder("#{Issue.table_name}.id").
|
|
| 71 | 71 |
to_a |
| 72 | 72 |
} |
| 73 | 73 |
format.api |
| app/helpers/my_helper.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 37 | 37 |
limit(10). |
| 38 | 38 |
includes(:status, :project, :tracker, :priority). |
| 39 | 39 |
references(:status, :project, :tracker, :priority). |
| 40 |
order("#{IssuePriority.table_name}.position DESC, #{Issue.table_name}.updated_on DESC")
|
|
| 40 |
order("#{IssuePriority.table_name}.#{'position'.quote_column_name} DESC, #{Issue.table_name}.updated_on DESC")
|
|
| 41 | 41 |
end |
| 42 | 42 | |
| 43 | 43 |
def issuesreportedbyme_items |
| ... | ... | |
| 69 | 69 |
joins(:activity, :project). |
| 70 | 70 |
references(:issue => [:tracker, :status]). |
| 71 | 71 |
includes(:issue => [:tracker, :status]). |
| 72 |
order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.position ASC, #{Issue.table_name}.id ASC").
|
|
| 72 |
order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.#{'position'.quote_column_name} ASC, #{Issue.table_name}.id ASC").
|
|
| 73 | 73 |
to_a |
| 74 | 74 |
end |
| 75 | 75 |
end |
| app/models/custom_field.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 243 | 243 | |
| 244 | 244 |
# to move in project_custom_field |
| 245 | 245 |
def self.for_all |
| 246 |
where(:is_for_all => true).order('position').to_a
|
|
| 246 |
where(:is_for_all => true).order(:position).to_a
|
|
| 247 | 247 |
end |
| 248 | 248 | |
| 249 | 249 |
def type_name |
| app/models/enumeration.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 18 | 18 |
class Enumeration < ActiveRecord::Base |
| 19 | 19 |
include Redmine::SubclassFactory |
| 20 | 20 | |
| 21 |
default_scope lambda {order(:position)}
|
|
| 21 |
default_scope lambda { order(:position) }
|
|
| 22 | 22 | |
| 23 | 23 |
belongs_to :project |
| 24 | 24 | |
| ... | ... | |
| 150 | 150 |
super |
| 151 | 151 |
if position_changed? |
| 152 | 152 |
self.class.where.not(:parent_id => nil).update_all( |
| 153 |
"position = coalesce((
|
|
| 154 |
select position
|
|
| 155 |
from (select id, position from enumerations) as parent
|
|
| 153 |
"#{'position'.quote_column_name} = coalesce((
|
|
| 154 |
select #{'position'.quote_column_name}
|
|
| 155 |
from (select id, #{'position'.quote_column_name} from enumerations) as parent
|
|
| 156 | 156 |
where parent_id = parent.id), 1)" |
| 157 | 157 |
) |
| 158 | 158 |
end |
| app/models/issue.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 1548 | 1548 |
if p.priority_derived? |
| 1549 | 1549 |
# priority = highest priority of open children |
| 1550 | 1550 |
# priority is left unchanged if all children are closed and there's no default priority defined |
| 1551 |
if priority_position = p.children.open.joins(:priority).maximum("#{IssuePriority.table_name}.position")
|
|
| 1551 |
if priority_position = p.children.open.joins(:priority).maximum("#{IssuePriority.table_name.quote_table_name}.#{'position'.quote_column_name}")
|
|
| 1552 | 1552 |
p.priority = IssuePriority.find_by_position(priority_position) |
| 1553 | 1553 |
elsif default_priority = IssuePriority.default |
| 1554 | 1554 |
p.priority = default_priority |
| app/models/issue_query.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 23 | 23 |
self.available_columns = [ |
| 24 | 24 |
QueryColumn.new(:id, :sortable => "#{Issue.table_name}.id", :default_order => 'desc', :caption => '#', :frozen => true),
|
| 25 | 25 |
QueryColumn.new(:project, :sortable => "#{Project.table_name}.name", :groupable => true),
|
| 26 |
QueryColumn.new(:tracker, :sortable => "#{Tracker.table_name}.position", :groupable => true),
|
|
| 26 |
QueryColumn.new(:tracker, :sortable => "#{Tracker.table_name}.#{'position'.quote_column_name}", :groupable => true),
|
|
| 27 | 27 |
QueryColumn.new(:parent, :sortable => ["#{Issue.table_name}.root_id", "#{Issue.table_name}.lft ASC"], :default_order => 'desc', :caption => :field_parent_issue),
|
| 28 |
QueryColumn.new(:status, :sortable => "#{IssueStatus.table_name}.position", :groupable => true),
|
|
| 29 |
QueryColumn.new(:priority, :sortable => "#{IssuePriority.table_name}.position", :default_order => 'desc', :groupable => true),
|
|
| 28 |
QueryColumn.new(:status, :sortable => "#{IssueStatus.table_name}.#{'position'.quote_column_name}", :groupable => true),
|
|
| 29 |
QueryColumn.new(:priority, :sortable => "#{IssuePriority.table_name}.#{'position'.quote_column_name}", :default_order => 'desc', :groupable => true),
|
|
| 30 | 30 |
QueryColumn.new(:subject, :sortable => "#{Issue.table_name}.subject"),
|
| 31 | 31 |
QueryColumn.new(:author, :sortable => lambda {User.fields_for_order_statement("authors")}, :groupable => true),
|
| 32 | 32 |
QueryColumn.new(:assigned_to, :sortable => lambda {User.fields_for_order_statement}, :groupable => true),
|
| app/models/issue_status.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 95 | 95 |
subselect = "SELECT MAX(j.created_on) FROM #{Journal.table_name} j" +
|
| 96 | 96 |
" JOIN #{JournalDetail.table_name} d ON d.journal_id = j.id" +
|
| 97 | 97 |
" WHERE j.journalized_type = 'Issue' AND j.journalized_id = #{Issue.table_name}.id" +
|
| 98 |
" AND d.property = 'attr' AND d.prop_key = 'status_id' AND d.value = :status_id"
|
|
| 98 |
" AND d.property = 'attr' AND d.prop_key = 'status_id' AND d.#{'value'.quote_column_name} = :status_id"
|
|
| 99 | 99 |
Issue.where(:status_id => id, :closed_on => nil). |
| 100 |
update_all(["closed_on = (#{subselect})", {:status_id => id.to_s}])
|
|
| 100 |
update_all(["closed_on = (#{subselect})", {:status_id => id.to_s}])
|
|
| 101 | 101 | |
| 102 | 102 |
# Then we update issues that don't have a journal which means the |
| 103 | 103 |
# current status was set on creation |
| app/models/project.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 44 | 44 |
has_many :documents, :dependent => :destroy |
| 45 | 45 |
has_many :news, lambda {includes(:author)}, :dependent => :destroy
|
| 46 | 46 |
has_many :issue_categories, lambda {order("#{IssueCategory.table_name}.name")}, :dependent => :delete_all
|
| 47 |
has_many :boards, lambda {order("position ASC")}, :dependent => :destroy
|
|
| 47 |
has_many :boards, lambda { order(:position) }, :dependent => :destroy
|
|
| 48 | 48 |
has_one :repository, lambda {where(["is_default = ?", true])}
|
| 49 | 49 |
has_many :repositories, :dependent => :destroy |
| 50 | 50 |
has_many :changesets, :through => :repository |
| 51 | 51 |
has_one :wiki, :dependent => :destroy |
| 52 | 52 |
# Custom field for the project issues |
| 53 | 53 |
has_and_belongs_to_many :issue_custom_fields, |
| 54 |
lambda {order("#{CustomField.table_name}.position")},
|
|
| 54 |
lambda { order("#{CustomField.table_name}.#{'position'.quote_column_name}") },
|
|
| 55 | 55 |
:class_name => 'IssueCustomField', |
| 56 | 56 |
:join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
|
| 57 | 57 |
:association_foreign_key => 'custom_field_id' |
| app/models/query.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 823 | 823 | |
| 824 | 824 |
def sql_for_custom_field(field, operator, value, custom_field_id) |
| 825 | 825 |
db_table = CustomValue.table_name |
| 826 |
db_field = 'value' |
|
| 826 |
db_field = 'value'.quote_column_name
|
|
| 827 | 827 |
filter = @available_filters[field] |
| 828 | 828 |
return nil unless filter |
| 829 | 829 |
if filter[:field].format.target_class && filter[:field].format.target_class <= User |
| ... | ... | |
| 868 | 868 |
int_values = value.first.to_s.scan(/[+-]?\d+/).map(&:to_i).join(",")
|
| 869 | 869 |
if int_values.present? |
| 870 | 870 |
if is_custom_filter |
| 871 |
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}))"
|
|
| 871 |
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}))"
|
|
| 872 | 872 |
else |
| 873 | 873 |
sql = "#{db_table}.#{db_field} IN (#{int_values})"
|
| 874 | 874 |
end |
| ... | ... | |
| 877 | 877 |
end |
| 878 | 878 |
when :float |
| 879 | 879 |
if is_custom_filter |
| 880 |
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})"
|
|
| 880 |
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})"
|
|
| 881 | 881 |
else |
| 882 | 882 |
sql = "#{db_table}.#{db_field} BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5}"
|
| 883 | 883 |
end |
| ... | ... | |
| 906 | 906 |
sql = date_clause(db_table, db_field, parse_date(value.first), nil, is_custom_filter) |
| 907 | 907 |
else |
| 908 | 908 |
if is_custom_filter |
| 909 |
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})"
|
|
| 909 |
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})"
|
|
| 910 | 910 |
else |
| 911 | 911 |
sql = "#{db_table}.#{db_field} >= #{value.first.to_f}"
|
| 912 | 912 |
end |
| ... | ... | |
| 916 | 916 |
sql = date_clause(db_table, db_field, nil, parse_date(value.first), is_custom_filter) |
| 917 | 917 |
else |
| 918 | 918 |
if is_custom_filter |
| 919 |
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})"
|
|
| 919 |
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})"
|
|
| 920 | 920 |
else |
| 921 | 921 |
sql = "#{db_table}.#{db_field} <= #{value.first.to_f}"
|
| 922 | 922 |
end |
| ... | ... | |
| 926 | 926 |
sql = date_clause(db_table, db_field, parse_date(value[0]), parse_date(value[1]), is_custom_filter) |
| 927 | 927 |
else |
| 928 | 928 |
if is_custom_filter |
| 929 |
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})"
|
|
| 929 |
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})"
|
|
| 930 | 930 |
else |
| 931 | 931 |
sql = "#{db_table}.#{db_field} BETWEEN #{value[0].to_f} AND #{value[1].to_f}"
|
| 932 | 932 |
end |
| ... | ... | |
| 1078 | 1078 |
s = [] |
| 1079 | 1079 |
if from |
| 1080 | 1080 |
if from.is_a?(Date) |
| 1081 |
if Redmine::Database.firebird? |
|
| 1082 |
from = date_for_user_time_zone(from.year, from.month, from.day).yesterday.end_of_day.to_date |
|
| 1083 |
else |
|
| 1081 |
from = date_for_user_time_zone(from.year, from.month, from.day).yesterday.end_of_day |
|
| 1084 |
from = date_for_user_time_zone(from.year, from.month, from.day).yesterday.end_of_day |
|
| 1085 |
end |
|
| 1082 | 1086 |
else |
| 1083 | 1087 |
from = from - 1 # second |
| 1084 | 1088 |
end |
| ... | ... | |
| 1089 | 1093 |
end |
| 1090 | 1094 |
if to |
| 1091 | 1095 |
if to.is_a?(Date) |
| 1096 |
if Redmine::Database.firebird? |
|
| 1097 |
to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day.to_date |
|
| 1098 |
else |
|
| 1092 |
to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day |
|
| 1099 |
to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day |
|
| 1100 |
end |
|
| 1093 | 1101 |
end |
| 1094 | 1102 |
if self.class.default_timezone == :utc |
| 1095 | 1103 |
to = to.utc |
| app/models/repository.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 420 | 420 |
# Notes: |
| 421 | 421 |
# - this hash honnors the users mapping defined for the repository |
| 422 | 422 |
def stats_by_author |
| 423 |
commits = Changeset.where("repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id")
|
|
| 423 |
commits = Changeset.where("repository_id = ?", id).select("committer, user_id, count(*) as commit_count").group("committer, user_id")
|
|
| 424 | 424 | |
| 425 | 425 |
#TODO: restore ordering ; this line probably never worked |
| 426 | 426 |
#commits.to_a.sort! {|x, y| x.last <=> y.last}
|
| 427 | 427 | |
| 428 |
changes = Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id")
|
|
| 428 |
changes = Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", id).select("committer, user_id, count(*) as commit_count").group("committer, user_id")
|
|
| 429 | 429 | |
| 430 | 430 |
user_ids = changesets.map(&:user_id).compact.uniq |
| 431 | 431 |
authors_names = User.where(:id => user_ids).inject({}) do |memo, user|
|
| ... | ... | |
| 440 | 440 |
end |
| 441 | 441 |
hash[mapped_name] ||= { :commits_count => 0, :changes_count => 0 }
|
| 442 | 442 |
if element.is_a?(Changeset) |
| 443 |
hash[mapped_name][:commits_count] += element.count.to_i |
|
| 443 |
hash[mapped_name][:commits_count] += element.commit_count.to_i
|
|
| 444 | 444 |
else |
| 445 |
hash[mapped_name][:changes_count] += element.count.to_i |
|
| 445 |
hash[mapped_name][:changes_count] += element.commit_count.to_i
|
|
| 446 | 446 |
end |
| 447 | 447 |
hash |
| 448 | 448 |
end |
| app/models/time_entry_query.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 25 | 25 |
QueryColumn.new(:spent_on, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"], :default_order => 'desc', :groupable => true),
|
| 26 | 26 |
QueryColumn.new(:tweek, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"], :caption => l(:label_week)),
|
| 27 | 27 |
QueryColumn.new(:user, :sortable => lambda {User.fields_for_order_statement}, :groupable => true),
|
| 28 |
QueryColumn.new(:activity, :sortable => "#{TimeEntryActivity.table_name}.position", :groupable => true),
|
|
| 28 |
QueryColumn.new(:activity, :sortable => "#{TimeEntryActivity.table_name}.#{'position'.quote_column_name}", :groupable => true),
|
|
| 29 | 29 |
QueryColumn.new(:issue, :sortable => "#{Issue.table_name}.id"),
|
| 30 |
QueryAssociationColumn.new(:issue, :tracker, :caption => :field_tracker, :sortable => "#{Tracker.table_name}.position"),
|
|
| 31 |
QueryAssociationColumn.new(:issue, :status, :caption => :field_status, :sortable => "#{IssueStatus.table_name}.position"),
|
|
| 30 |
QueryAssociationColumn.new(:issue, :tracker, :caption => :field_tracker, :sortable => "#{Tracker.table_name}.#{'position'.quote_column_name}"),
|
|
| 31 |
QueryAssociationColumn.new(:issue, :status, :caption => :field_status, :sortable => "#{IssueStatus.table_name}.#{'position'.quote_column_name}"),
|
|
| 32 | 32 |
QueryColumn.new(:comments), |
| 33 | 33 |
QueryColumn.new(:hours, :sortable => "#{TimeEntry.table_name}.hours", :totalable => true),
|
| 34 | 34 |
] |
| app/models/user.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 683 | 683 |
# Returns true if the user is allowed to delete the user's own account |
| 684 | 684 |
def own_account_deletable? |
| 685 | 685 |
Setting.unsubscribe? && |
| 686 |
(!admin? || User.active.where("admin = ? AND id <> ?", true, id).exists?)
|
|
| 686 |
(!admin? || User.active.where("id <> ?", id).where(:admin => true).exists?)
|
|
| 687 | 687 |
end |
| 688 | 688 | |
| 689 | 689 |
safe_attributes 'firstname', |
| ... | ... | |
| 820 | 820 |
where(["property = 'attr' AND prop_key = 'assigned_to_id' AND old_value = ?", id.to_s]). |
| 821 | 821 |
update_all(['old_value = ?', substitute.id.to_s]) |
| 822 | 822 |
JournalDetail. |
| 823 |
where(["property = 'attr' AND prop_key = 'assigned_to_id' AND value = ?", id.to_s]). |
|
| 824 |
update_all(['value = ?', substitute.id.to_s]) |
|
| 823 |
where(["property = 'attr' AND prop_key = 'assigned_to_id'"]). |
|
| 824 |
where(:value => id.to_s). |
|
| 825 |
update_all(:value => substitute.id.to_s) |
|
| 825 | 826 |
Message.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) |
| 826 | 827 |
News.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) |
| 827 | 828 |
# Remove private queries and keep public ones |
| db/migrate/007_create_journals.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 22 | 22 |
end |
| 23 | 23 | |
| 24 | 24 |
# indexes |
| 25 |
add_index "journals", ["journalized_id", "journalized_type"], :name => "journals_journalized_id"
|
|
| 25 |
add_index "journals", ["journalized_id", "journalized_type"] |
|
| 26 | 26 |
add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id" |
| 27 | 27 | |
| 28 | 28 |
Permission.create :controller => "issues", :action => "history", :description => "label_history", :sort => 1006, :is_public => true, :mail_option => 0, :mail_enabled => 0 |
| db/migrate/072_add_enumerations_position.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 4 | 4 |
Enumeration.all.group_by(&:opt).each do |opt, enums| |
| 5 | 5 |
enums.each_with_index do |enum, i| |
| 6 | 6 |
# do not call model callbacks |
| 7 |
Enumeration.where({:id => enum.id}).update_all("position = #{i+1}")
|
|
| 7 |
Enumeration.where({:id => enum.id}).update_all(:position => (i+1))
|
|
| 8 | 8 |
end |
| 9 | 9 |
end |
| 10 | 10 |
end |
| db/migrate/078_add_custom_fields_position.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 4 | 4 |
CustomField.all.group_by(&:type).each do |t, fields| |
| 5 | 5 |
fields.each_with_index do |field, i| |
| 6 | 6 |
# do not call model callbacks |
| 7 |
CustomField.where({:id => field.id}).update_all("position = #{i+1}")
|
|
| 7 |
CustomField.where({:id => field.id}).update_all(:position => (i+1))
|
|
| 8 | 8 |
end |
| 9 | 9 |
end |
| 10 | 10 |
end |
| db/migrate/107_add_open_id_authentication_tables.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 1 | 1 |
class AddOpenIdAuthenticationTables < ActiveRecord::Migration |
| 2 | 2 |
def self.up |
| 3 |
create_table :open_id_authentication_associations, :force => true do |t|
|
|
| 3 |
create_table :open_id_auth_associations, :force => true do |t| |
|
| 4 | 4 |
t.integer :issued, :lifetime |
| 5 | 5 |
t.string :handle, :assoc_type |
| 6 | 6 |
t.binary :server_url, :secret |
| 7 | 7 |
end |
| 8 | 8 | |
| 9 |
create_table :open_id_authentication_nonces, :force => true do |t|
|
|
| 9 |
create_table :open_id_auth_nonces, :force => true do |t| |
|
| 10 | 10 |
t.integer :timestamp, :null => false |
| 11 | 11 |
t.string :server_url, :null => true |
| 12 | 12 |
t.string :salt, :null => false |
| ... | ... | |
| 14 | 14 |
end |
| 15 | 15 | |
| 16 | 16 |
def self.down |
| 17 |
drop_table :open_id_authentication_associations
|
|
| 18 |
drop_table :open_id_authentication_nonces
|
|
| 17 |
drop_table :open_id_auth_associations |
|
| 18 |
drop_table :open_id_auth_nonces |
|
| 19 | 19 |
end |
| 20 | 20 |
end |
| db/migrate/20130201184705_add_unique_index_on_tokens_value.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 2 | 2 |
def up |
| 3 | 3 |
say_with_time "Adding unique index on tokens, this may take some time..." do |
| 4 | 4 |
# Just in case |
| 5 |
duplicates = Token.connection.select_values("SELECT value FROM #{Token.table_name} GROUP BY value HAVING COUNT(id) > 1")
|
|
| 5 |
duplicates = Token.group(:value).having('COUNT(id) > 1').select(:value).to_a
|
|
| 6 | 6 |
Token.where(:value => duplicates).delete_all |
| 7 | 7 |
|
| 8 | 8 |
add_index :tokens, :value, :unique => true, :name => 'tokens_value' |
| db/migrate/20130215111141_populate_issues_closed_on.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 10 | 10 |
" AND #{Journal.table_name}.journalized_type = 'Issue' AND #{Journal.table_name}.journalized_id = #{Issue.table_name}.id" +
|
| 11 | 11 |
" AND #{JournalDetail.table_name}.property = 'attr' AND #{JournalDetail.table_name}.prop_key = 'status_id'" +
|
| 12 | 12 |
" AND #{JournalDetail.table_name}.old_value NOT IN (#{closed_status_values})" +
|
| 13 |
" AND #{JournalDetail.table_name}.value IN (#{closed_status_values})"
|
|
| 13 |
" AND #{JournalDetail.table_name}.#{'value'.quote_column_name} IN (#{closed_status_values})"
|
|
| 14 | 14 |
Issue.update_all "closed_on = (#{subselect})"
|
| 15 | 15 | |
| 16 | 16 |
# Then set closed_on for closed issues that weren't up updated by the above UPDATE |
| db/migrate/20141029181824_remove_issue_statuses_is_default.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 6 | 6 |
def down |
| 7 | 7 |
add_column :issue_statuses, :is_default, :boolean, :null => false, :default => false |
| 8 | 8 |
# Restores the first status as default |
| 9 |
default_status_id = IssueStatus.order("position").pluck(:id).first
|
|
| 9 |
default_status_id = IssueStatus.order(:position).pluck(:id).first
|
|
| 10 | 10 |
IssueStatus.where(:id => default_status_id).update_all(:is_default => true) |
| 11 | 11 |
end |
| 12 | 12 |
end |
| lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb (revision 99c2c157b5953ec1878ea20163950d82305736b4) | ||
|---|---|---|
| 27 | 27 |
return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods) |
| 28 | 28 |
cattr_accessor :customizable_options |
| 29 | 29 |
self.customizable_options = options |
| 30 |
has_many :custom_values, lambda {includes(:custom_field).order("#{CustomField.table_name}.position")},
|
|
| 30 |
has_many :custom_values, lambda {joins(:custom_field).merge(CustomField.order(:position))},
|
|
| 31 | 31 |
:as => :customized, |
| 32 | 32 |
:dependent => :delete_all, |
| 33 | 33 |
:validate => false |
| lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb (revision 364ef1c03d27f869907e6c2bf43b7176ba0ee716) | ||
|---|---|---|
| 112 | 112 |
search_scope(user, projects, options). |
| 113 | 113 |
joins(:custom_values). |
| 114 | 114 |
where(visibility). |
| 115 |
where(search_tokens_condition(["#{CustomValue.table_name}.value"], tokens, options[:all_words])),
|
|
| 115 |
where(search_tokens_condition(["#{CustomValue.table_name}.#{'value'.quote_column_name}"], tokens, options[:all_words])),
|
|
| 116 | 116 |
options[:limit] |
| 117 | 117 |
) |
| 118 | 118 |
queries += 1 |
| lib/plugins/open_id_authentication/lib/open_id_authentication/association.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 1 | 1 |
module OpenIdAuthentication |
| 2 | 2 |
class Association < ActiveRecord::Base |
| 3 |
self.table_name = :open_id_authentication_associations
|
|
| 3 |
self.table_name = :open_id_auth_associations |
|
| 4 | 4 | |
| 5 | 5 |
def from_record |
| 6 | 6 |
OpenID::Association.new(handle, secret, issued, lifetime, assoc_type) |
| lib/redmine/acts/positioned.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 84 | 84 |
end |
| 85 | 85 |
end |
| 86 | 86 | |
| 87 |
def position_column |
|
| 88 |
'position'.quote_column_name |
|
| 89 |
end |
|
| 90 | ||
| 87 | 91 |
def insert_position |
| 88 |
position_scope.where("position >= ? AND id <> ?", position, id).update_all("position = position + 1")
|
|
| 92 |
position_scope.where("#{position_column} >= ? AND id <> ?", position, id).update_all("#{position_column} = #{position_column} + 1")
|
|
| 89 | 93 |
end |
| 90 | 94 | |
| 91 | 95 |
def remove_position |
| 92 |
position_scope_was.where("position >= ? AND id <> ?", position_was, id).update_all("position = position - 1")
|
|
| 96 |
position_scope_was.where("#{position_column} >= ? AND id <> ?", position_was, id).update_all("#{position_column} = #{position_column} - 1")
|
|
| 93 | 97 |
end |
| 94 | 98 | |
| 95 | 99 |
def position_scope_changed? |
| ... | ... | |
| 99 | 103 |
def shift_positions |
| 100 | 104 |
offset = position_was <=> position |
| 101 | 105 |
min, max = [position, position_was].sort |
| 102 |
r = position_scope.where("id <> ? AND position BETWEEN ? AND ?", id, min, max).update_all("position = position + #{offset}")
|
|
| 106 |
r = position_scope.where("id <> ? AND #{position_column} BETWEEN ? AND ?", id, min, max).update_all("#{position_column} = #{position_column} + #{offset}")
|
|
| 103 | 107 |
if r != max - min |
| 104 | 108 |
reset_positions_in_list |
| 105 | 109 |
end |
| lib/redmine/core_ext/string.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 8 | 8 |
def is_binary_data? |
| 9 | 9 |
( self.count( "^ -~", "^\r\n" ).fdiv(self.size) > 0.3 || self.index( "\x00" ) ) unless empty? |
| 10 | 10 |
end |
| 11 | ||
| 12 |
def quote_column_name |
|
| 13 |
ActiveRecord::Base.connection.quote_column_name(self) |
|
| 14 |
end |
|
| 15 | ||
| 16 |
def quote_table_name |
|
| 17 |
ActiveRecord::Base.connection.quote_table_name(self) |
|
| 18 |
end |
|
| 11 | 19 |
end |
| lib/redmine/database.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 49 | 49 |
(ActiveRecord::Base.connection.adapter_name =~ /mysql/i).present? |
| 50 | 50 |
end |
| 51 | 51 | |
| 52 |
# Returns +true+ if the database is Firebird or RedDatabase |
|
| 53 |
def firebird? |
|
| 54 |
(ActiveRecord::Base.connection.adapter_name =~ /fb/i).present? |
|
| 55 |
end |
|
| 56 | ||
| 52 | 57 |
# Returns a SQL statement for case/accent (if possible) insensitive match |
| 53 | 58 |
def like(left, right, options={})
|
| 54 | 59 |
neg = (options[:match] == false ? 'NOT ' : '') |
| lib/redmine/field_format.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 265 | 265 |
# Returns nil if the custom field can not be used for sorting. |
| 266 | 266 |
def order_statement(custom_field) |
| 267 | 267 |
# COALESCE is here to make sure that blank and NULL values are sorted equally |
| 268 |
"COALESCE(#{join_alias custom_field}.value, '')"
|
|
| 268 |
"COALESCE(#{join_alias custom_field}.#{value_column}, '')"
|
|
| 269 | 269 |
end |
| 270 | 270 | |
| 271 | 271 |
# Returns a GROUP BY clause that can used to group by custom value |
| ... | ... | |
| 283 | 283 |
" AND #{alias_name}.customized_id = #{custom_field.class.customized_class.table_name}.id" +
|
| 284 | 284 |
" AND #{alias_name}.custom_field_id = #{custom_field.id}" +
|
| 285 | 285 |
" AND (#{custom_field.visibility_by_project_condition})" +
|
| 286 |
" AND #{alias_name}.value <> ''" +
|
|
| 286 |
" AND #{alias_name}.#{value_column} <> ''" +
|
|
| 287 | 287 |
" AND #{alias_name}.id = (SELECT max(#{alias_name}_2.id) FROM #{CustomValue.table_name} #{alias_name}_2" +
|
| 288 | 288 |
" WHERE #{alias_name}_2.customized_type = #{alias_name}.customized_type" +
|
| 289 | 289 |
" AND #{alias_name}_2.customized_id = #{alias_name}.customized_id" +
|
| ... | ... | |
| 293 | 293 |
def join_alias(custom_field) |
| 294 | 294 |
"cf_#{custom_field.id}"
|
| 295 | 295 |
end |
| 296 | ||
| 297 |
def value_column |
|
| 298 |
'value'.quote_column_name |
|
| 299 |
end |
|
| 296 | 300 |
protected :join_alias |
| 297 | 301 |
end |
| 298 | 302 | |
| ... | ... | |
| 402 | 406 |
# Make the database cast values into numeric |
| 403 | 407 |
# Postgresql will raise an error if a value can not be casted! |
| 404 | 408 |
# CustomValue validations should ensure that it doesn't occur |
| 405 |
"CAST(CASE #{join_alias custom_field}.value WHEN '' THEN '0' ELSE #{join_alias custom_field}.value END AS decimal(30,3))"
|
|
| 409 |
"CAST(CASE #{join_alias custom_field}.#{value_column} WHEN '' THEN '0' ELSE #{join_alias custom_field}.#{value_column} END AS decimal(18,3))"
|
|
| 406 | 410 |
end |
| 407 | 411 | |
| 408 | 412 |
# Returns totals for the given scope |
| ... | ... | |
| 410 | 414 |
scope.joins(:custom_values). |
| 411 | 415 |
where(:custom_values => {:custom_field_id => custom_field.id}).
|
| 412 | 416 |
where.not(:custom_values => {:value => ''}).
|
| 413 |
sum("CAST(#{CustomValue.table_name}.value AS decimal(30,3))")
|
|
| 417 |
sum("CAST(#{CustomValue.table_name}.#{value_column} AS decimal(18,3))")
|
|
| 414 | 418 |
end |
| 415 | 419 | |
| 416 | 420 |
def cast_total_value(custom_field, value) |
| ... | ... | |
| 690 | 694 |
end |
| 691 | 695 | |
| 692 | 696 |
def group_statement(custom_field) |
| 693 |
"COALESCE(#{join_alias custom_field}.value, '')"
|
|
| 697 |
"COALESCE(#{join_alias custom_field}.#{value_column}, '')"
|
|
| 694 | 698 |
end |
| 695 | 699 | |
| 696 | 700 |
def join_for_order_statement(custom_field) |
| ... | ... | |
| 701 | 705 |
" AND #{alias_name}.customized_id = #{custom_field.class.customized_class.table_name}.id" +
|
| 702 | 706 |
" AND #{alias_name}.custom_field_id = #{custom_field.id}" +
|
| 703 | 707 |
" AND (#{custom_field.visibility_by_project_condition})" +
|
| 704 |
" AND #{alias_name}.value <> ''" +
|
|
| 708 |
" AND #{alias_name}.#{value_column} <> ''" +
|
|
| 705 | 709 |
" AND #{alias_name}.id = (SELECT max(#{alias_name}_2.id) FROM #{CustomValue.table_name} #{alias_name}_2" +
|
| 706 | 710 |
" WHERE #{alias_name}_2.customized_type = #{alias_name}.customized_type" +
|
| 707 | 711 |
" AND #{alias_name}_2.customized_id = #{alias_name}.customized_id" +
|
| 708 | 712 |
" AND #{alias_name}_2.custom_field_id = #{alias_name}.custom_field_id)" +
|
| 709 | 713 |
" LEFT OUTER JOIN #{target_class.table_name} #{value_join_alias custom_field}" +
|
| 710 |
" ON CAST(CASE #{alias_name}.value WHEN '' THEN '0' ELSE #{alias_name}.value END AS decimal(30,0)) = #{value_join_alias custom_field}.id"
|
|
| 714 |
" 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"
|
|
| 711 | 715 |
end |
| 712 | 716 | |
| 713 | 717 |
def value_join_alias(custom_field) |
| lib/tasks/migrate_from_mantis.rake (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 52 | 52 |
TRACKER_BUG = Tracker.find_by_position(1) |
| 53 | 53 |
TRACKER_FEATURE = Tracker.find_by_position(2) |
| 54 | 54 | |
| 55 |
roles = Role.where(:builtin => 0).order('position ASC').all
|
|
| 55 |
roles = Role.where(:builtin => 0).order(:position).all
|
|
| 56 | 56 |
manager_role = roles[0] |
| 57 | 57 |
developer_role = roles[1] |
| 58 | 58 |
DEFAULT_ROLE = roles.last |
| lib/tasks/migrate_from_trac.rake (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 60 | 60 |
'patch' =>TRACKER_FEATURE |
| 61 | 61 |
} |
| 62 | 62 | |
| 63 |
roles = Role.where(:builtin => 0).order('position ASC').all
|
|
| 63 |
roles = Role.where(:builtin => 0).order(:position).all
|
|
| 64 | 64 |
manager_role = roles[0] |
| 65 | 65 |
developer_role = roles[1] |
| 66 | 66 |
DEFAULT_ROLE = roles.last |
| test/unit/query_test.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 161 | 161 |
query = IssueQuery.new(:project => Project.find(1), :name => '_') |
| 162 | 162 |
query.add_filter('fixed_version_id', '!*', [''])
|
| 163 | 163 |
query.add_filter('cf_1', '!*', [''])
|
| 164 |
value_col = 'value'.quote_column_name |
|
| 164 | 165 |
assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL")
|
| 165 |
assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''")
|
|
| 166 |
assert query.statement.include?("#{CustomValue.table_name}.#{value_col} IS NULL OR #{CustomValue.table_name}.#{value_col} = ''")
|
|
| 166 | 167 |
find_issues_with_query(query) |
| 167 | 168 |
end |
| 168 | 169 | |
| ... | ... | |
| 196 | 197 |
query = IssueQuery.new(:project => Project.find(1), :name => '_') |
| 197 | 198 |
query.add_filter('fixed_version_id', '*', [''])
|
| 198 | 199 |
query.add_filter('cf_1', '*', [''])
|
| 200 |
value_col = 'value'.quote_column_name |
|
| 199 | 201 |
assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL")
|
| 200 |
assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''")
|
|
| 202 |
assert query.statement.include?("#{CustomValue.table_name}.#{value_col} IS NOT NULL AND #{CustomValue.table_name}.#{value_col} <> ''")
|
|
| 201 | 203 |
find_issues_with_query(query) |
| 202 | 204 |
end |
| 203 | 205 | |
| test/unit/user_test.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 1051 | 1051 |
end |
| 1052 | 1052 | |
| 1053 | 1053 |
def test_own_account_deletable_should_be_false_for_a_single_admin |
| 1054 |
User.where(["admin = ? AND id <> ?", true, 1]).delete_all
|
|
| 1054 |
User.where(["id <> ?", 1]).where(:admin => true).delete_all
|
|
| 1055 | 1055 | |
| 1056 | 1056 |
with_settings :unsubscribe => '1' do |
| 1057 | 1057 |
assert_equal false, User.find(1).own_account_deletable? |
| test/object_helpers.rb (revision c2f792010966f726d9c2eabff00956159df88715) | ||
|---|---|---|
| 65 | 65 |
@generated_tracker_name.succ! |
| 66 | 66 |
tracker = Tracker.new(attributes) |
| 67 | 67 |
tracker.name = @generated_tracker_name.dup if tracker.name.blank? |
| 68 |
tracker.default_status ||= IssueStatus.order('position').first || IssueStatus.generate!
|
|
| 68 |
tracker.default_status ||= IssueStatus.order(:position).first || IssueStatus.generate!
|
|
| 69 | 69 |
yield tracker if block_given? |
| 70 | 70 |
tracker |
| 71 | 71 |
end |