OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/db/migrate/20170829095701_generate_wp_...

233 lines
6.4 KiB

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 the OpenProject GmbH
#
# 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-2013 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 COPYRIGHT and LICENSE files for more details.
#++
class GenerateWpClosure < ActiveRecord::Migration[5.0]
def up
add_relation_type_column
update_relation_column_from_relation_type
invert_from_to_on_follows("relation_type = 'precedes'")
insert_hierarchy_relation_for_parent
remove_column :relations, :relation_type
remove_nested_set_columns
end
def down
recreate_nested_set_columns
invert_from_to_on_follows('follows = 1')
set_parent_id
remove_hierarchy_relations
fill_relation_type_column
remove_relation_type_specific_columns
rebuild_nested_set
end
def relation_types
%i(hierarchy relates duplicates blocks follows includes requires)
end
def add_relation_type_column
change_table :relations do |r|
relation_types.each do |column|
r.column column, :integer, default: 0, null: false
end
end
end
def remove_nested_set_columns
remove_column :work_packages, :parent_id
remove_column :work_packages, :root_id
remove_column :work_packages, :lft
remove_column :work_packages, :rgt
end
def recreate_nested_set_columns
add_column :work_packages, :parent_id, :integer
add_column :work_packages, :root_id, :integer
add_column :work_packages, :lft, :integer
add_column :work_packages, :rgt, :integer
add_index :work_packages, :parent_id
add_index :work_packages, %i(root_id lft rgt)
end
def remove_hierarchy_relations
ActiveRecord::Base.connection.execute <<-SQL
DELETE FROM relations
WHERE hierarchy > 0
SQL
end
def invert_from_to_on_follows(condition)
if ActiveRecord::Base.connection.adapter_name == 'Mysql2'
ActiveRecord::Base.connection.execute <<-SQL
UPDATE
relations r1,
relations r2
SET
r1.to_id = r1.from_id,
r1.from_id = r2.to_id
WHERE
r1.id = r2.id
AND
r1.#{condition}
SQL
else
ActiveRecord::Base.connection.execute <<-SQL
UPDATE
relations
SET
from_id = to_id,
to_id = from_id
WHERE
#{condition}
SQL
end
end
def update_relation_column_from_relation_type
ActiveRecord::Base.connection.execute <<-SQL
UPDATE
relations
SET
relates = CASE
WHEN relations.relation_type = 'relates'
THEN 1
ELSE 0
END,
duplicates = CASE
WHEN relations.relation_type = 'duplicates'
THEN 1
ELSE 0
END,
blocks = CASE
WHEN relations.relation_type = 'blocks'
THEN 1
ELSE 0
END,
follows = CASE
WHEN relations.relation_type = 'precedes'
THEN 1
ELSE 0
END,
includes = CASE
WHEN relations.relation_type = 'includes'
THEN 1
ELSE 0
END,
requires = CASE
WHEN relations.relation_type = 'requires'
THEN 1
ELSE 0
END
SQL
end
def insert_hierarchy_relation_for_parent
ActiveRecord::Base.connection.execute <<-SQL
INSERT INTO relations
(from_id, to_id, hierarchy)
SELECT w1.id, w2.id, 1
FROM work_packages w1
JOIN work_packages w2
ON w1.id = w2.parent_id
SQL
end
def set_parent_id
ActiveRecord::Base.connection.execute <<-SQL
UPDATE
work_packages
SET
parent_id =
(SELECT from_id
FROM relations
WHERE to_id = work_packages.id
AND relations.hierarchy = 1
AND relations.relates = 0
AND relations.duplicates = 0
AND relations.blocks = 0
AND relations.follows = 0
AND relations.includes = 0
AND relations.requires = 0)
SQL
end
def fill_relation_type_column
add_column :relations, :relation_type, :string
ActiveRecord::Base.connection.execute <<-SQL
UPDATE
relations
SET
relation_type = CASE
WHEN relations.relates = 1
THEN 'relates'
WHEN relations.duplicates = 1
THEN 'duplicates'
WHEN relations.duplicates = 1
THEN 'blocks'
WHEN relations.follows = 1
THEN 'precedes'
WHEN relations.includes = 1
THEN 'includes'
WHEN relations.requires = 1
THEN 'requires'
END
SQL
end
def remove_relation_type_specific_columns
relation_types.each do |column|
remove_column :relations, column
end
end
def rebuild_nested_set
NestedSetWorkPackage.rebuild_silently!
end
class NestedSetWorkPackage < ActiveRecord::Base
self.table_name = 'work_packages'
acts_as_nested_set scope: 'root_id', dependent: :destroy
include OpenProject::NestedSet::RebuildPatch
end
end