2019-05-02 18:17:27 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-03-20 03:20:50 -04:00
|
|
|
module Migration
|
|
|
|
class BaseDropper
|
2020-04-30 02:48:34 -04:00
|
|
|
FUNCTION_SCHEMA_NAME ||= "discourse_functions"
|
2018-08-23 00:51:22 -04:00
|
|
|
|
2018-03-20 03:20:50 -04:00
|
|
|
def self.create_readonly_function(table_name, column_name = nil)
|
2018-08-23 00:51:22 -04:00
|
|
|
DB.exec <<~SQL
|
|
|
|
CREATE SCHEMA IF NOT EXISTS #{FUNCTION_SCHEMA_NAME};
|
|
|
|
SQL
|
|
|
|
|
2018-03-20 03:20:50 -04:00
|
|
|
message = column_name ?
|
|
|
|
"Discourse: #{column_name} in #{table_name} is readonly" :
|
|
|
|
"Discourse: #{table_name} is read only"
|
|
|
|
|
2018-06-19 02:13:14 -04:00
|
|
|
DB.exec <<~SQL
|
2018-03-20 03:20:50 -04:00
|
|
|
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
|
|
|
|
|
2019-08-08 10:06:27 -04:00
|
|
|
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)
|
2018-08-23 00:51:22 -04:00
|
|
|
function_name = [
|
|
|
|
"raise",
|
|
|
|
table_name,
|
|
|
|
column_name,
|
|
|
|
"readonly()"
|
|
|
|
].compact.join("_")
|
|
|
|
|
2019-08-08 10:06:27 -04:00
|
|
|
if with_schema && function_schema_exists?
|
2018-09-17 02:44:29 -04:00
|
|
|
"#{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}.", ''
|
|
|
|
)
|
2018-03-20 03:20:50 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.readonly_trigger_name(table_name, column_name = nil)
|
|
|
|
[table_name, column_name, "readonly"].compact.join("_")
|
|
|
|
end
|
2019-08-08 10:06:27 -04:00
|
|
|
|
|
|
|
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
|
|
|
|
FROM information_schema.routines
|
|
|
|
WHERE routine_type = 'FUNCTION' AND specific_schema = '#{FUNCTION_SCHEMA_NAME}'
|
|
|
|
SQL
|
|
|
|
end
|
2018-03-20 03:20:50 -04:00
|
|
|
end
|
|
|
|
end
|