Extend legacy journal migration

The legacy journal migration now includes normalization into the data
tables. This involves combining previous journals (diffs) into the new
normalized schema and extends to changesets, news, messages and work
packages.
pull/374/head
Martin Czuchra 11 years ago
parent d653bea4d0
commit 74c0adc9c5
  1. 122
      db/migrate/20130823113842_migrate_legacy_journals.rb

@ -9,21 +9,85 @@ class MigrateLegacyJournals < ActiveRecord::Migration
def up def up
check_assumptions check_assumptions
fetch_legacy_journals.each do |journal| previous_journaled_id, previous_type = 0, ""
previous_journal = {}
journal_tables = {
"ChangesetJournal" => "changeset_journals",
"NewsJournal" => "news_journals",
"MessageJournal" => "message_journals",
"WorkPackageJournal" => "work_package_journals"
}
fetch_legacy_journals.each do |legacy_journal|
# turn id fields into integers. # turn id fields into integers.
["id", "journaled_id", "user_id", "version"].each do |f| ["id", "journaled_id", "user_id", "version"].each do |f|
journal[f] = journal[f].to_i legacy_journal[f] = legacy_journal[f].to_i
end end
journal["changed_data"] = YAML.load(journal["changed_data"]) legacy_journal["changed_data"] = YAML.load(legacy_journal["changed_data"])
get_journal journal["journaled_id"], journaled_id, type, version = legacy_journal["journaled_id"], legacy_journal["type"], legacy_journal["version"]
journal["type"], table = journal_tables[type]
journal["version"]
end if table.nil?
puts "Ignoring type `#{type}`"
next
end
# actually insert/update stuff in the database.
journal = get_journal(journaled_id, type, version)
journal_id = journal["id"]
# update the journal w/ all values not previously inserted.
execute <<-SQL
UPDATE journals
SET journable_data_id = 0,
journable_data_type = #{quote_value(type)},
user_id = #{quote_value(legacy_journal["user_id"])},
notes = #{quote_value(legacy_journal["notes"])},
created_at = #{quote_value(legacy_journal["created_at"])},
activity_type = #{quote_value(legacy_journal["activity_type"])}
WHERE id = #{quote_value(journal_id)};
SQL
# compute the combined journal from current and all previous changesets.
combined_journal = legacy_journal["changed_data"]
if previous_journaled_id == journaled_id && previous_type == type
combined_journal = previous_journal.merge(combined_journal)
end
binding.pry # remember the combined journal as the previous one for the next iteration.
previous_journal = combined_journal
previous_journaled_id = journaled_id
previous_type = type
data = fetch_journal_data(journal_id, table)
if data.size > 1
raise AmbiguousJournalsError, <<-MESSAGE.split("\n").map(&:strip!).join(" ") + "\n"
It appears there are ambiguous journal data. Please make sure
journal data are consistent and that the unique constraint on
journal_id is met.
MESSAGE
elsif data.size == 0
keys = combined_journal.keys
values = combined_journal.values.map(&:last)
execute <<-SQL
INSERT INTO #{quoted_table_name(table)}(journal_id, #{keys.join(", ")})
VALUES (#{quote_value(journal_id)}, #{values.map{|d| quote_value(d)}.join(", ")});
SQL
end
(data || fetch_journal_data(journal_id, table)).first
end
end end
@ -32,7 +96,16 @@ class MigrateLegacyJournals < ActiveRecord::Migration
private private
# gets a journal, and makes sure it has a valid id in the database. # fetches specific journal data row. might be empty.
def fetch_journal_data(journal_id, table)
ActiveRecord::Base.connection.select_all <<-SQL
SELECT *
FROM #{quoted_table_name(table)} AS d
WHERE d.journal_id = #{quote_value(journal_id)};
SQL
end
# gets a journal row, and makes sure it has a valid id in the database.
def get_journal(id, type, version) def get_journal(id, type, version)
journal = fetch_journal(id, type, version) journal = fetch_journal(id, type, version)
@ -40,46 +113,49 @@ class MigrateLegacyJournals < ActiveRecord::Migration
raise AmbiguousJournalsError, <<-MESSAGE.split("\n").map(&:strip!).join(" ") + "\n" raise AmbiguousJournalsError, <<-MESSAGE.split("\n").map(&:strip!).join(" ") + "\n"
It appears there are ambiguous journals. Please make sure It appears there are ambiguous journals. Please make sure
journals are consistent and that the unique constraing on id, journals are consistent and that the unique constraint on id,
type and version is met. type and version is met.
MESSAGE MESSAGE
elsif journal.size == 0 elsif journal.size == 0
execute <<-SQL execute <<-SQL
INSERT INTO journals(journable_id, journable_type, version, created_at) INSERT INTO #{quoted_journals_table_name}(journable_id, journable_type, version, created_at)
VALUES ( VALUES (
#{quote_value(id)}, #{quote_value(id)},
#{quote_value(type)}, #{quote_value(type)},
#{quote_value(version)}, #{quote_value(version)},
#{quote_value(Time.now)} #{quote_value(Time.now)}
) );
SQL SQL
journal = fetch_journal(id, type, version)
end end
journal || fetch_journal(id, type, version) journal.first
end end
# fetches legacy journals. might me empty. # fetches specific journal row. might be empty.
def fetch_legacy_journals def fetch_journal(id, type, version)
ActiveRecord::Base.connection.select_all <<-SQL ActiveRecord::Base.connection.select_all <<-SQL
SELECT * SELECT *
FROM #{quoted_legacy_journals_table_name} AS j FROM #{quoted_journals_table_name} AS j
ORDER BY j.journaled_id, j.activity_type, j.version WHERE j.journable_id = #{quote_value(id)}
AND j.journable_type = #{quote_value(type)}
AND j.version = #{quote_value(version)};
SQL SQL
end end
# fetches specific journal. might be empty. # fetches legacy journals. might me empty.
def fetch_journal(id, type, version) def fetch_legacy_journals
ActiveRecord::Base.connection.select_all <<-SQL ActiveRecord::Base.connection.select_all <<-SQL
SELECT * SELECT *
FROM #{quoted_journals_table_name} AS j FROM #{quoted_legacy_journals_table_name} AS j
WHERE j.journable_id = #{quote_value(id)} ORDER BY j.journaled_id, j.activity_type, j.version;
AND j.journable_type = #{quote_value(type)}
AND j.version = #{quote_value(version)}
SQL SQL
end end
def quote_value name def quote_value name
ActiveRecord::Base.connection.quote name ActiveRecord::Base.connection.quote name
end end

Loading…
Cancel
Save