mirror of
https://github.com/discourse/discourse.git
synced 2024-11-26 14:03:39 +08:00
DEV: Correct historical schema discrepancies (#9955)
Rails schema defaults have changed over the years. This migration will correct discrepancies, and make all databases match the modern schema.
This commit is contained in:
parent
833b5d89e0
commit
f7d676dce1
249
db/migrate/20200601130900_correct_schema_discrepancies.rb
Normal file
249
db/migrate/20200601130900_correct_schema_discrepancies.rb
Normal file
|
@ -0,0 +1,249 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CorrectSchemaDiscrepancies < ActiveRecord::Migration[6.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
timestamp_columns = %w{
|
||||
category_tag_groups.created_at
|
||||
category_tag_groups.updated_at
|
||||
category_tags.created_at
|
||||
category_tags.updated_at
|
||||
child_themes.created_at
|
||||
child_themes.updated_at
|
||||
embeddable_hosts.created_at
|
||||
embeddable_hosts.updated_at
|
||||
group_archived_messages.created_at
|
||||
group_archived_messages.updated_at
|
||||
group_mentions.created_at
|
||||
group_mentions.updated_at
|
||||
muted_users.created_at
|
||||
muted_users.updated_at
|
||||
permalinks.created_at
|
||||
permalinks.updated_at
|
||||
post_stats.created_at
|
||||
post_stats.updated_at
|
||||
remote_themes.created_at
|
||||
remote_themes.updated_at
|
||||
stylesheet_cache.created_at
|
||||
stylesheet_cache.updated_at
|
||||
tag_group_memberships.created_at
|
||||
tag_group_memberships.updated_at
|
||||
tag_groups.created_at
|
||||
tag_groups.updated_at
|
||||
tag_users.created_at
|
||||
tag_users.updated_at
|
||||
tags.created_at
|
||||
tags.updated_at
|
||||
theme_fields.created_at
|
||||
theme_fields.updated_at
|
||||
topic_tags.created_at
|
||||
topic_tags.updated_at
|
||||
topic_timers.created_at
|
||||
topic_timers.updated_at
|
||||
unsubscribe_keys.created_at
|
||||
unsubscribe_keys.updated_at
|
||||
user_api_keys.created_at
|
||||
user_api_keys.updated_at
|
||||
user_archived_messages.created_at
|
||||
user_archived_messages.updated_at
|
||||
user_auth_tokens.created_at
|
||||
user_auth_tokens.updated_at
|
||||
user_emails.created_at
|
||||
user_emails.updated_at
|
||||
user_exports.created_at
|
||||
user_exports.updated_at
|
||||
user_field_options.created_at
|
||||
user_field_options.updated_at
|
||||
user_fields.created_at
|
||||
user_fields.updated_at
|
||||
user_warnings.created_at
|
||||
user_warnings.updated_at
|
||||
watched_words.created_at
|
||||
watched_words.updated_at
|
||||
web_hook_events.created_at
|
||||
web_hook_events.updated_at
|
||||
web_hooks.created_at
|
||||
web_hooks.updated_at
|
||||
}
|
||||
|
||||
char_limit_columns = %w{
|
||||
badge_groupings.name
|
||||
badge_posts.action_code
|
||||
badge_posts.edit_reason
|
||||
badge_types.name
|
||||
badges.icon
|
||||
badges.name
|
||||
categories.email_in
|
||||
categories.slug
|
||||
color_scheme_colors.hex
|
||||
color_scheme_colors.name
|
||||
color_schemes.name
|
||||
draft_sequences.draft_key
|
||||
drafts.draft_key
|
||||
email_logs.email_type
|
||||
email_logs.to_address
|
||||
email_tokens.email
|
||||
email_tokens.token
|
||||
embeddable_hosts.host
|
||||
github_user_infos.screen_name
|
||||
groups.name
|
||||
groups.title
|
||||
invites.email
|
||||
message_bus.context
|
||||
message_bus.name
|
||||
oauth2_user_infos.email
|
||||
oauth2_user_infos.name
|
||||
oauth2_user_infos.provider
|
||||
oauth2_user_infos.uid
|
||||
optimized_images.url
|
||||
plugin_store_rows.key
|
||||
plugin_store_rows.plugin_name
|
||||
plugin_store_rows.type_name
|
||||
post_details.key
|
||||
post_details.value
|
||||
post_search_data.locale
|
||||
posts.action_code
|
||||
posts.edit_reason
|
||||
schema_migrations.version
|
||||
screened_emails.email
|
||||
screened_urls.domain
|
||||
screened_urls.url
|
||||
single_sign_on_records.external_email
|
||||
single_sign_on_records.external_id
|
||||
single_sign_on_records.external_name
|
||||
single_sign_on_records.external_username
|
||||
site_settings.name
|
||||
stylesheet_cache.digest
|
||||
stylesheet_cache.target
|
||||
themes.name
|
||||
topic_links.title
|
||||
topic_search_data.locale
|
||||
topics.archetype
|
||||
topics.slug
|
||||
topics.subtype
|
||||
topics.title
|
||||
uploads.original_filename
|
||||
uploads.url
|
||||
user_exports.file_name
|
||||
user_field_options.value
|
||||
user_fields.description
|
||||
user_fields.field_type
|
||||
user_fields.name
|
||||
user_histories.context
|
||||
user_histories.custom_type
|
||||
user_histories.email
|
||||
user_histories.ip_address
|
||||
user_open_ids.email
|
||||
user_open_ids.url
|
||||
user_profiles.location
|
||||
user_profiles.website
|
||||
users.name
|
||||
users.title
|
||||
}
|
||||
|
||||
float_default_columns = %w{
|
||||
top_topics.all_score
|
||||
top_topics.daily_score
|
||||
top_topics.monthly_score
|
||||
top_topics.weekly_score
|
||||
top_topics.yearly_score
|
||||
}
|
||||
|
||||
other_default_columns = %w{
|
||||
categories.color
|
||||
topic_search_data.topic_id
|
||||
}
|
||||
|
||||
lookup_sql = (
|
||||
timestamp_columns +
|
||||
char_limit_columns +
|
||||
float_default_columns +
|
||||
other_default_columns
|
||||
).map do |ref|
|
||||
table, column = ref.split(".")
|
||||
"(table_name='#{table}' AND column_name='#{column}')"
|
||||
end.join(" OR ")
|
||||
|
||||
raw_info = DB.query_hash <<~SQL
|
||||
SELECT table_name, column_name, is_nullable, character_maximum_length, column_default
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema='public'
|
||||
AND (
|
||||
#{lookup_sql}
|
||||
)
|
||||
SQL
|
||||
|
||||
schema_hash = {}
|
||||
|
||||
raw_info.each do |row|
|
||||
schema_hash["#{row["table_name"]}.#{row["column_name"]}"] = row
|
||||
end
|
||||
|
||||
# In the past, rails changed the default behavior for timestamp columns
|
||||
# This only affects older discourse installations
|
||||
# This migration will make old database schemas match modern behavior
|
||||
timestamp_columns.each do |ref|
|
||||
current_value = schema_hash[ref]["is_nullable"]
|
||||
next if current_value == "NO"
|
||||
|
||||
table, column = ref.split(".")
|
||||
|
||||
# There shouldn't be any null values - rails inserts timestamps automatically
|
||||
# But just in case, set them to now() if there are any nulls
|
||||
DB.exec <<~SQL
|
||||
UPDATE #{table} SET #{column} = now() WHERE #{column} IS NULL
|
||||
SQL
|
||||
|
||||
DB.exec <<~SQL
|
||||
ALTER TABLE #{table} ALTER COLUMN #{column} SET NOT NULL
|
||||
SQL
|
||||
end
|
||||
|
||||
# In the past, rails changed the default behavior for varchar columns
|
||||
# This only affects older discourse installations
|
||||
# This migration removes the character limits from columns, so that they match modern behavior
|
||||
char_limit_columns.each do |ref|
|
||||
current_value = schema_hash[ref]["character_maximum_length"]
|
||||
next if current_value == nil
|
||||
table, column = ref.split(".")
|
||||
|
||||
DB.exec <<~SQL
|
||||
ALTER TABLE #{table} ALTER COLUMN #{column} TYPE varchar
|
||||
SQL
|
||||
end
|
||||
|
||||
# In the past, rails changed the default behavior for float columns
|
||||
# This only affects older discourse installations
|
||||
# This migration updates the default values, so that they match modern behavior
|
||||
float_default_columns.each do |ref|
|
||||
current_value = schema_hash[ref]["column_default"]
|
||||
next if current_value == "0.0"
|
||||
table, column = ref.split(".")
|
||||
|
||||
DB.exec <<~SQL
|
||||
ALTER TABLE #{table} ALTER COLUMN #{column} SET DEFAULT 0.0
|
||||
SQL
|
||||
end
|
||||
|
||||
# Category color default was changed in https://github.com/discourse/discourse/commit/faf09bb8c80fcb28b132a5a644ac689cc9abffc2
|
||||
# But should have been added in a new migration
|
||||
if schema_hash["categories.color"]["column_default"] != "'0088CC'::character varying"
|
||||
DB.exec <<~SQL
|
||||
ALTER TABLE categories ALTER COLUMN color SET DEFAULT '0088CC'
|
||||
SQL
|
||||
end
|
||||
|
||||
# Older sites have a default value like nextval('topic_search_data_topic_id_seq'::regclass)
|
||||
# Modern sites do not. This is likely caused by another historical change in rails
|
||||
if schema_hash["topic_search_data.topic_id"]["column_default"] != nil
|
||||
DB.exec <<~SQL
|
||||
ALTER TABLE topic_search_data ALTER COLUMN topic_id SET DEFAULT NULL
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user