From b475eb435619a97ee183fd716720e682433e07ae Mon Sep 17 00:00:00 2001 From: Raul Marin Date: Mon, 28 Oct 2019 14:08:07 +0100 Subject: [PATCH] Federated Server List --- scripts-available/CDB_FederatedServer.sql | 70 +++++++++++++++++++++ scripts-enabled/400-CDB_FederatedServer.sql | 1 + test/CDB_FederatedServer.sql | 43 +++++++++++++ test/CDB_FederatedServer_expect | 0 4 files changed, 114 insertions(+) create mode 100644 scripts-available/CDB_FederatedServer.sql create mode 120000 scripts-enabled/400-CDB_FederatedServer.sql create mode 100644 test/CDB_FederatedServer.sql create mode 100644 test/CDB_FederatedServer_expect diff --git a/scripts-available/CDB_FederatedServer.sql b/scripts-available/CDB_FederatedServer.sql new file mode 100644 index 0000000..46af6d8 --- /dev/null +++ b/scripts-available/CDB_FederatedServer.sql @@ -0,0 +1,70 @@ + +-- This function is just a placement to store and use the pattern for +-- foreign server names +CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Name_Pattern() +RETURNS TEXT +AS $$ + SELECT 'cdb_fs_'; +$$ +LANGUAGE SQL IMMUTABLE PARALLEL SAFE; + + +-- Produce a valid DB name for objects created for the user FDW's +CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Object_Name(fdw_input_name NAME) +RETURNS NAME +AS $$ +DECLARE + object_name text := format('%s%s', @extschema@.__CDB_FS_Name_Pattern(), fdw_input_name); +BEGIN + -- We discard anything that would be truncated + IF (char_length(object_name) < 64) THEN + RETURN object_name::name; + ELSE + RAISE EXCEPTION 'Object name is too long to be used as identifier'; + END IF; +END +$$ +LANGUAGE PLPGSQL IMMUTABLE PARALLEL SAFE; + + + +-- List registered servers +-- TODO: Decide whether we want to show extra config (extensions, fetch_size, use_remote_estimate)s +CREATE OR REPLACE FUNCTION @extschema@.CDB_Federated_Server_List_Servers(fdw_pattern TEXT DEFAULT '%') +RETURNS TABLE ( + name text, + driver text, + host text, + port text, + dbname text, + readmode text, + username text +) +AS $$ +DECLARE + server_name text := concat(@extschema@.__CDB_FS_Name_Pattern() || fdw_pattern); +BEGIN + RETURN QUERY SELECT + -- Name as shown to the user + right(s.srvname, char_length(s.srvname::TEXT) - char_length(@extschema@.__CDB_FS_Name_Pattern()))::TEXT AS "Name", + + -- Which driver are we using (postgres_fdw, odbc_fdw...) + f.fdwname::text AS "Driver", + + -- Read + (SELECT option_value FROM pg_options_to_table(s.srvoptions) WHERE option_name LIKE 'host') AS "Host", + (SELECT option_value FROM pg_options_to_table(s.srvoptions) WHERE option_name LIKE 'port') AS "Port", + (SELECT option_value FROM pg_options_to_table(s.srvoptions) WHERE option_name LIKE 'dbname') AS "DBName", + CASE WHEN (SELECT NOT option_value::boolean FROM pg_options_to_table(s.srvoptions) WHERE option_name LIKE 'updatable') THEN 'read-only' ELSE 'read-write' END AS "ReadMode", + + -- Read username from 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 + ORDER BY 1; +END +$$ +LANGUAGE PLPGSQL IMMUTABLE PARALLEL SAFE; diff --git a/scripts-enabled/400-CDB_FederatedServer.sql b/scripts-enabled/400-CDB_FederatedServer.sql new file mode 120000 index 0000000..6a3df9a --- /dev/null +++ b/scripts-enabled/400-CDB_FederatedServer.sql @@ -0,0 +1 @@ +../scripts-available/CDB_FederatedServer.sql \ No newline at end of file diff --git a/test/CDB_FederatedServer.sql b/test/CDB_FederatedServer.sql new file mode 100644 index 0000000..dd25170 --- /dev/null +++ b/test/CDB_FederatedServer.sql @@ -0,0 +1,43 @@ +-- Setup +\set QUIET on +SET client_min_messages TO error; +SET SESSION AUTHORIZATION postgres; +\set QUIET off + +-- Register a new server +SELECT '1.1', cartodb.CDB_Federated_Server_List_Servers(); +-- SELECT '1.2', cartodb.CDB_Federated_Server_Register_PG(); +-- SELECT '1.3', cartodb.CDB_Federated_Server_List_Servers(); +-- +-- Register a second server +-- SELECT '2.1', cartodb.CDB_Federated_Server_Register_PG(); +-- SELECT '2.2', cartodb.CDB_PG_Federated_Server_List_Servers(); +-- +-- Re-register the second server +-- SELECT '3.1', cartodb.CDB_Federated_Server_Register_PG(); +-- SELECT '3.2', cartodb.CDB_PG_Federated_Server_List_Servers(); +-- +-- Unregister #1 +-- SELECT '4.1', cartodb.CDB_PG_Federated_Server_Unregister(); +-- SELECT '4.2', cartodb.CDB_PG_Federated_Server_List_Servers(); +-- +-- Unregister #2 +-- SELECT '5.1', cartodb.CDB_PG_Federated_Server_Unregister(); +-- SELECT '5.2', cartodb.CDB_PG_Federated_Server_List_Servers(); + +-- Should show the appropiate output (database, read-write, user, pass) + +-- Test multiple user mappings + +-- Should work ok with special characters in the name + +-- Should throw with invalid or NULL config + +-- -- List works with multiple and single server + +-- Cleanup +\set QUIET on + +\set QUIET off + + diff --git a/test/CDB_FederatedServer_expect b/test/CDB_FederatedServer_expect new file mode 100644 index 0000000..e69de29