2017-05-12 15:01:43 -04:00
|
|
|
class TableMigrationHelper
|
|
|
|
def self.read_only_table(table_name)
|
|
|
|
ActiveRecord::Base.exec_sql <<-SQL
|
2018-03-08 02:05:21 -05:00
|
|
|
CREATE OR REPLACE FUNCTION #{readonly_function_name(table_name)} RETURNS trigger AS $rro$
|
2017-05-12 15:01:43 -04:00
|
|
|
BEGIN
|
2017-05-30 17:35:52 -04:00
|
|
|
RAISE EXCEPTION 'Discourse: Table is read only';
|
2017-05-12 15:01:43 -04:00
|
|
|
RETURN null;
|
|
|
|
END
|
|
|
|
$rro$ LANGUAGE plpgsql;
|
|
|
|
SQL
|
|
|
|
|
|
|
|
ActiveRecord::Base.exec_sql <<-SQL
|
2018-03-08 02:05:21 -05:00
|
|
|
CREATE TRIGGER #{readonly_trigger_name(table_name)}
|
2017-05-12 15:01:43 -04:00
|
|
|
BEFORE INSERT OR UPDATE OR DELETE OR TRUNCATE
|
|
|
|
ON #{table_name}
|
|
|
|
FOR EACH STATEMENT
|
2018-03-08 02:05:21 -05:00
|
|
|
EXECUTE PROCEDURE #{readonly_function_name(table_name)};
|
2017-05-12 15:01:43 -04:00
|
|
|
SQL
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.delayed_drop(old_name:, new_name:, after_migration:, delay: nil, on_drop: nil)
|
2018-03-08 02:05:21 -05:00
|
|
|
delay ||= Rails.env.production? ? 3600 : 0
|
2017-05-12 15:01:43 -04:00
|
|
|
|
2018-03-08 02:05:21 -05:00
|
|
|
sql = <<~SQL
|
2017-05-12 15:01:43 -04:00
|
|
|
SELECT 1
|
|
|
|
FROM INFORMATION_SCHEMA.TABLES
|
|
|
|
WHERE table_schema = 'public' AND
|
|
|
|
EXISTS (
|
|
|
|
SELECT 1
|
|
|
|
FROM schema_migration_details
|
|
|
|
WHERE name = :after_migration AND
|
|
|
|
created_at <= (current_timestamp at time zone 'UTC' - interval :delay)
|
|
|
|
)
|
|
|
|
AND EXISTS (
|
|
|
|
SELECT 1
|
|
|
|
FROM INFORMATION_SCHEMA.TABLES
|
|
|
|
WHERE table_schema = 'public' AND
|
|
|
|
table_name = :new_name
|
|
|
|
)
|
|
|
|
LIMIT 1
|
2018-03-08 02:05:21 -05:00
|
|
|
SQL
|
2017-05-12 15:01:43 -04:00
|
|
|
|
|
|
|
if ActiveRecord::Base.exec_sql(sql, old_name: old_name,
|
|
|
|
new_name: new_name,
|
|
|
|
delay: "#{delay.to_i || 0} seconds",
|
|
|
|
after_migration: after_migration).to_a.length > 0
|
2018-03-08 02:05:21 -05:00
|
|
|
|
2017-07-27 21:20:09 -04:00
|
|
|
on_drop&.call
|
2018-03-08 02:05:21 -05:00
|
|
|
ActiveRecord::Base.exec_sql("DROP TABLE IF EXISTS #{old_name}")
|
2017-05-12 15:01:43 -04:00
|
|
|
|
2018-03-08 02:05:21 -05:00
|
|
|
ActiveRecord::Base.exec_sql <<~SQL
|
|
|
|
DROP FUNCTION IF EXISTS #{readonly_function_name(old_name)} CASCADE;
|
|
|
|
SQL
|
2017-05-12 15:01:43 -04:00
|
|
|
end
|
|
|
|
end
|
2018-03-08 02:05:21 -05:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def self.readonly_function_name(table_name)
|
|
|
|
"public.raise_#{table_name}_read_only()"
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.readonly_trigger_name(table_name)
|
|
|
|
"#{table_name}_read_only"
|
|
|
|
end
|
2017-05-12 15:01:43 -04:00
|
|
|
end
|