67 lines
2.3 KiB
Ruby
67 lines
2.3 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
class ReplaceExternalWikiTriggers < ActiveRecord::Migration[6.1]
|
||
|
include Gitlab::Database::SchemaHelpers
|
||
|
|
||
|
def up
|
||
|
replace_triggers('type_new', 'Integrations::ExternalWiki')
|
||
|
|
||
|
# we need an extra trigger to handle when type_new is updated by the
|
||
|
# `integrations_set_type_new` trigger.
|
||
|
# This can be removed when this trigger has been removed.
|
||
|
execute(<<~SQL.squish)
|
||
|
CREATE TRIGGER #{trigger_name(:type_new_updated)}
|
||
|
AFTER UPDATE OF type_new ON integrations FOR EACH ROW
|
||
|
WHEN ((new.type_new)::text = 'Integrations::ExternalWiki'::text AND new.project_id IS NOT NULL)
|
||
|
EXECUTE FUNCTION set_has_external_wiki();
|
||
|
SQL
|
||
|
end
|
||
|
|
||
|
def down
|
||
|
execute("DROP TRIGGER IF EXISTS #{trigger_name(:type_new_updated)} ON integrations;")
|
||
|
replace_triggers('type', 'ExternalWikiService')
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def replace_triggers(column_name, value)
|
||
|
triggers(column_name, value).each do |event, condition|
|
||
|
trigger = trigger_name(event)
|
||
|
|
||
|
# create duplicate trigger, using the defined condition
|
||
|
execute(<<~SQL.squish)
|
||
|
CREATE TRIGGER #{trigger}_new AFTER #{event.upcase} ON integrations FOR EACH ROW
|
||
|
WHEN (#{condition})
|
||
|
EXECUTE FUNCTION set_has_external_wiki();
|
||
|
SQL
|
||
|
|
||
|
# Swap the triggers in place, so that the new trigger has the canonical name
|
||
|
execute("ALTER TRIGGER #{trigger} ON integrations RENAME TO #{trigger}_old;")
|
||
|
execute("ALTER TRIGGER #{trigger}_new ON integrations RENAME TO #{trigger};")
|
||
|
|
||
|
# remove the old, now redundant trigger
|
||
|
execute("DROP TRIGGER IF EXISTS #{trigger}_old ON integrations;")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def trigger_name(event)
|
||
|
"trigger_has_external_wiki_on_#{event}"
|
||
|
end
|
||
|
|
||
|
def triggers(column_name, value)
|
||
|
{
|
||
|
delete: "#{matches_value('old', column_name, value)} AND #{project_not_null('old')}",
|
||
|
insert: "(new.active = true) AND #{matches_value('new', column_name, value)} AND #{project_not_null('new')}",
|
||
|
update: "#{matches_value('new', column_name, value)} AND (old.active <> new.active) AND #{project_not_null('new')}"
|
||
|
}
|
||
|
end
|
||
|
|
||
|
def project_not_null(row)
|
||
|
"(#{row}.project_id IS NOT NULL)"
|
||
|
end
|
||
|
|
||
|
def matches_value(row, column_name, value)
|
||
|
"((#{row}.#{column_name})::text = '#{value}'::text)"
|
||
|
end
|
||
|
end
|