#-- copyright # OpenProject is a project management system. # # Copyright (C) 2012-2013 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. # # See doc/COPYRIGHT.rdoc for more details. #++ module Migration module Utils UpdateResult = Struct.new(:row, :updated) def say_with_time_silently message say_with_time message do suppress_messages do yield end end end def filter(columns, terms) column_filters = [] columns.each do |column| filters = terms.map {|term| "#{column} LIKE '%#{term}%'"} column_filters << "(#{filters.join(' OR ')})" end column_filters.join(' OR ') end def update_column_values(table, column_list, updater, conditions) update_column_values_and_journals(table, column_list, updater, false, conditions) end def update_column_values_and_journals(table, column_list, updater, update_journal, conditions) processed_rows = [] select_rows_from_database(table, column_list, conditions).each do |row| processed_rows << updater.call(row) end updated_rows = processed_rows.select(&:updated) update_rows_in_database(table, column_list, updated_rows.collect(&:row)) update_journals(table, updated_rows) if update_journal end def reset_public_key_sequence_in_postgres(table) return unless ActiveRecord::Base.connection.instance_values["config"][:adapter] == "postgresql" ActiveRecord::Base.connection.reset_pk_sequence!(table) end def postgres? ActiveRecord::Base.connection.instance_values["config"][:adapter] == "postgresql" end def mysql? ActiveRecord::Base.connection.instance_values["config"][:adapter] == "mysql2" end private def select_rows_from_database(table, column_list, conditions) columns = (column_list.nil?) ? '' : ', ' + column_list.join(', ') from_clause = table where_clause = conditions.nil? ? '1 = 1' : conditions select_all <<-SQL SELECT id#{columns} FROM #{from_clause} WHERE #{where_clause} SQL end def update_rows_in_database(table, column_list, updated_rows) columns = (column_list.nil?) ? '' : column_list.join(', ') updated_rows.each do |row| values = column_list.map {|c| "#{c}=#{quote(row[c])}"} .join(', ') update <<-SQL UPDATE #{table} SET #{values} WHERE id = #{row['id']} SQL end end def update_journals(table, updated_rows) created_journals = {} updated_ids = updated_rows.collect {|r| r.row['id']} journal_table = "#{table.singularize}_journals" journable_type = table.classify updated_ids.each do |id| created_journals[id] = insert <<-SQL INSERT INTO journals (journable_id, journable_type, user_id, created_at, version, activity_type) SELECT journable_id, journable_type, #{system_user_id}, NOW(), MAX(version) + 1, activity_type FROM journals WHERE journable_type = '#{journable_type}' AND journable_id = #{id} GROUP BY journable_id, journable_type, activity_type; SQL end journal_table_columns = journal_table_columns(journal_table) insert <<-SQL INSERT INTO #{journal_table} (journal_id, #{journal_table_columns.join(", ")}) SELECT j.id AS journal_id, #{journal_table_columns.collect{|c| "w.#{c}"}.join(", ")} FROM journals AS j JOIN #{table} AS w ON (j.journable_id = w.id) WHERE journable_type = '#{journable_type}' AND j.id NOT IN (SELECT journal_id FROM work_package_journals) SQL end def system_user_id @system_user_id ||= User.system.id end def journal_table_columns(table) "Journal::#{table.classify}".constantize.column_names - ['id', 'journal_id'] end end end