Add federated server list remotes
Includes: - CDB_Federated_Server_List_Remote_Schemas - CDB_Federated_Server_List_Remote_Tables
This commit is contained in:
@@ -11,20 +11,19 @@ AS $$
|
||||
$$
|
||||
LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
|
||||
-- Produce a valid DB name for servers generated for the Federated Server
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Generate_Server_Name(input_name TEXT, check_existence BOOL)
|
||||
RETURNS NAME
|
||||
AS $$
|
||||
DECLARE
|
||||
object_name text := format('%s%s', @extschema@.__CDB_FS_Name_Pattern(), input_name);
|
||||
internal_server_name text := format('%s%s', @extschema@.__CDB_FS_Name_Pattern(), input_name);
|
||||
BEGIN
|
||||
-- We discard anything that would be truncated
|
||||
IF (char_length(object_name) < 64) THEN
|
||||
IF (check_existence AND (NOT EXISTS (SELECT * FROM pg_foreign_server WHERE srvname = object_name))) THEN
|
||||
IF (char_length(internal_server_name) < 64) THEN
|
||||
IF (check_existence AND (NOT EXISTS (SELECT * FROM pg_foreign_server WHERE srvname = internal_server_name))) THEN
|
||||
RAISE EXCEPTION 'Server "%" does not exist', input_name;
|
||||
END IF;
|
||||
RETURN object_name::name;
|
||||
RETURN internal_server_name::name;
|
||||
ELSE
|
||||
RAISE EXCEPTION 'Server name is too long to be used as identifier';
|
||||
END IF;
|
||||
@@ -32,21 +31,20 @@ END
|
||||
$$
|
||||
LANGUAGE PLPGSQL IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Extract_Server_Name(fdw_stored_name NAME)
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Extract_Server_Name(internal_server_name NAME)
|
||||
RETURNS TEXT
|
||||
AS $$
|
||||
SELECT right(fdw_stored_name,
|
||||
char_length(fdw_stored_name::TEXT) - char_length(@extschema@.__CDB_FS_Name_Pattern()))::TEXT;
|
||||
SELECT right(internal_server_name,
|
||||
char_length(internal_server_name::TEXT) - char_length(@extschema@.__CDB_FS_Name_Pattern()))::TEXT;
|
||||
$$
|
||||
LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
-- Produce a valid name for a schema generated for the Federated Server
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Generate_Schema_Name(server_name TEXT, schema_name TEXT)
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Generate_Schema_Name(internal_server_name TEXT, schema_name TEXT)
|
||||
RETURNS NAME
|
||||
AS $$
|
||||
DECLARE
|
||||
server_full_name text := @extschema@.__CDB_FS_Generate_Server_Name(server_name, check_existence := true);
|
||||
hash_value text := md5(server_full_name::text || '__' || schema_name::text);
|
||||
hash_value text := md5(internal_server_name::text || '__' || schema_name::text);
|
||||
schema_name text := format('%s%s%s', @extschema@.__CDB_FS_Name_Pattern(), 'schema_', hash_value);
|
||||
BEGIN
|
||||
RETURN schema_name::name;
|
||||
@@ -56,12 +54,11 @@ LANGUAGE PLPGSQL IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
-- Produce a valid name for a role generated for the Federated Server
|
||||
-- This needs to include the current database in its hash to avoid collisions in clusters with more than one database
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Generate_Server_Role_Name(server_name TEXT)
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Generate_Server_Role_Name(internal_server_name TEXT)
|
||||
RETURNS NAME
|
||||
AS $$
|
||||
DECLARE
|
||||
server_full_name text := @extschema@.__CDB_FS_Generate_Server_Name(server_name, check_existence := true);
|
||||
hash_value text := md5(current_database()::text || '__' || server_full_name::text);
|
||||
hash_value text := md5(current_database()::text || '__' || internal_server_name::text);
|
||||
role_name text := format('%s%s%s', @extschema@.__CDB_FS_Name_Pattern(), 'role_', hash_value);
|
||||
BEGIN
|
||||
RETURN role_name::name;
|
||||
@@ -70,22 +67,36 @@ $$
|
||||
LANGUAGE PLPGSQL IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
-- Creates (if not exist) a schema to place the objects for a remote schema
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Create_Schema(server_name TEXT, schema_name TEXT)
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Create_Schema(internal_server_name TEXT, schema_name TEXT)
|
||||
RETURNS NAME
|
||||
AS $$
|
||||
DECLARE
|
||||
schema_name text := @extschema@.__CDB_FS_Generate_Schema_Name(server_name, schema_name);
|
||||
role_name text := @extschema@.__CDB_FS_Generate_Server_Role_Name(server_name);
|
||||
schema_name text := @extschema@.__CDB_FS_Generate_Schema_Name(internal_server_name, schema_name);
|
||||
role_name text := @extschema@.__CDB_FS_Generate_Server_Role_Name(internal_server_name);
|
||||
BEGIN
|
||||
BEGIN
|
||||
EXECUTE 'CREATE SCHEMA IF NOT EXISTS ' || quote_ident(schema_name) || ' AUTHORIZATION ' || quote_ident(role_name);
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE EXCEPTION 'TODO: This needs a better error handling after reviewing permissions';
|
||||
END;
|
||||
IF NOT EXISTS (SELECT oid FROM pg_namespace WHERE nspname = schema_name) THEN
|
||||
BEGIN
|
||||
EXECUTE 'CREATE SCHEMA IF NOT EXISTS ' || quote_ident(schema_name) || ' AUTHORIZATION ' || quote_ident(role_name);
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE EXCEPTION 'TODO: This needs a better error handling after reviewing permissions: %', SQLERRM;
|
||||
END;
|
||||
END IF;
|
||||
RETURN schema_name;
|
||||
END
|
||||
$$
|
||||
LANGUAGE PLPGSQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Returns the type of a server by internal name
|
||||
CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_server_type(remote_server name)
|
||||
RETURNS name
|
||||
AS $$
|
||||
SELECT f.fdwname
|
||||
FROM pg_foreign_server s
|
||||
JOIN pg_foreign_data_wrapper f ON s.srvfdw = f.oid
|
||||
WHERE s.srvname = remote_server;
|
||||
$$
|
||||
LANGUAGE SQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
|
||||
-- List registered servers
|
||||
-- TODO: Decide whether we want to show extra config (extensions, fetch_size, use_remote_estimate)
|
||||
@@ -109,7 +120,7 @@ BEGIN
|
||||
@extschema@.__CDB_FS_Extract_Server_Name(s.srvname) AS "Name",
|
||||
|
||||
-- Which driver are we using (postgres_fdw, odbc_fdw...)
|
||||
f.fdwname::text AS "Driver",
|
||||
@extschema@.__CDB_FS_server_type(s.srvname)::text AS "Driver",
|
||||
|
||||
-- Read options from pg_foreign_server
|
||||
(SELECT option_value FROM pg_options_to_table(s.srvoptions) WHERE option_name LIKE 'host') AS "Host",
|
||||
@@ -120,7 +131,6 @@ BEGIN
|
||||
-- Read username from pg_user_mappings
|
||||
(SELECT option_value FROM pg_options_to_table(u.umoptions) WHERE option_name LIKE 'user') AS "Username"
|
||||
FROM pg_foreign_server s
|
||||
JOIN pg_foreign_data_wrapper f ON f.oid=s.srvfdw
|
||||
LEFT JOIN pg_user_mappings u
|
||||
ON u.srvid = s.oid
|
||||
WHERE s.srvname ILIKE server_name
|
||||
@@ -137,10 +147,13 @@ AS $$
|
||||
DECLARE
|
||||
user_mapping jsonb := json_build_object(
|
||||
'user_mapping',
|
||||
jsonb_build_object('user', input_config->'credentials'->'username',
|
||||
'password', input_config->'credentials'->'password')
|
||||
jsonb_build_object( 'user', input_config->'credentials'->'username',
|
||||
'password', input_config->'credentials'->'password')
|
||||
);
|
||||
BEGIN
|
||||
IF NOT (input_config ? 'credentials') THEN
|
||||
RAISE EXCEPTION 'Credentials are mandatory';
|
||||
END IF;
|
||||
RETURN (input_config - 'credentials')::jsonb || user_mapping;
|
||||
END
|
||||
$$
|
||||
@@ -174,7 +187,7 @@ AS $$
|
||||
DECLARE
|
||||
server_internal name := @extschema@.__CDB_FS_Generate_Server_Name(input_name := server, check_existence := false);
|
||||
final_config json := @extschema@.__CDB_FS_credentials_to_user_mapping(@extschema@.__CDB_FS_add_default_options(config));
|
||||
role_name name;
|
||||
role_name name := @extschema@.__CDB_FS_Generate_Server_Role_Name(server_internal);
|
||||
row record;
|
||||
option record;
|
||||
BEGIN
|
||||
@@ -187,7 +200,6 @@ BEGIN
|
||||
IF NOT EXISTS (SELECT * FROM pg_foreign_server WHERE srvname = server_internal) THEN
|
||||
BEGIN
|
||||
EXECUTE FORMAT('CREATE SERVER %I FOREIGN DATA WRAPPER postgres_fdw', server_internal);
|
||||
role_name := @extschema@.__CDB_FS_Generate_Server_Role_Name(server);
|
||||
EXECUTE FORMAT('CREATE ROLE %I NOLOGIN', role_name);
|
||||
EXECUTE FORMAT('GRANT USAGE ON FOREIGN DATA WRAPPER postgres_fdw TO %I', role_name);
|
||||
EXECUTE FORMAT('GRANT USAGE ON FOREIGN SERVER %I TO %I', server_internal, role_name);
|
||||
@@ -238,7 +250,7 @@ RETURNS void
|
||||
AS $$
|
||||
DECLARE
|
||||
server_internal text := @extschema@.__CDB_FS_Generate_Server_Name(input_name := server, check_existence := true);
|
||||
role_name name := @extschema@.__CDB_FS_Generate_Server_Role_Name(server);
|
||||
role_name name := @extschema@.__CDB_FS_Generate_Server_Role_Name(server_internal);
|
||||
BEGIN
|
||||
EXECUTE FORMAT ('DROP USER MAPPING FOR public SERVER %I', server_internal);
|
||||
EXECUTE FORMAT ('DROP OWNED BY %I CASCADE', role_name);
|
||||
|
||||
Reference in New Issue
Block a user