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