discourse/lib/migration/base_dropper.rb
2023-01-09 12:10:19 +00:00

69 lines
2.0 KiB
Ruby

# frozen_string_literal: true
module Migration
class BaseDropper
FUNCTION_SCHEMA_NAME ||= "discourse_functions"
def self.create_readonly_function(table_name, column_name = nil)
DB.exec <<~SQL
CREATE SCHEMA IF NOT EXISTS #{FUNCTION_SCHEMA_NAME};
SQL
message =
(
if column_name
"Discourse: #{column_name} in #{table_name} is readonly"
else
"Discourse: #{table_name} is read only"
end
)
DB.exec <<~SQL
CREATE OR REPLACE FUNCTION #{readonly_function_name(table_name, column_name)} RETURNS trigger AS $rcr$
BEGIN
RAISE EXCEPTION '#{message}';
END
$rcr$ LANGUAGE plpgsql;
SQL
end
def self.drop_readonly_function(table_name, column_name = nil)
DB.exec("DROP FUNCTION IF EXISTS #{readonly_function_name(table_name, column_name)} CASCADE")
end
def self.readonly_function_name(table_name, column_name = nil, with_schema: true)
function_name = ["raise", table_name, column_name, "readonly()"].compact.join("_")
if with_schema && function_schema_exists?
"#{FUNCTION_SCHEMA_NAME}.#{function_name}"
else
function_name
end
end
def self.old_readonly_function_name(table_name, column_name = nil)
readonly_function_name(table_name, column_name).sub("#{FUNCTION_SCHEMA_NAME}.", "")
end
def self.readonly_trigger_name(table_name, column_name = nil)
[table_name, column_name, "readonly"].compact.join("_")
end
def self.function_schema_exists?
DB.exec(<<~SQL).to_s == "1"
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name = '#{FUNCTION_SCHEMA_NAME}'
SQL
end
def self.existing_discourse_function_names
DB.query_single(<<~SQL)
SELECT routine_name::text
FROM information_schema.routines
WHERE routine_type = 'FUNCTION' AND specific_schema = '#{FUNCTION_SCHEMA_NAME}'
SQL
end
end
end