CREATE SCHEMA run_command_on_all_nodes;
SET search_path TO run_command_on_all_nodes;
SELECT master_remove_node('localhost', :master_port);
 master_remove_node
---------------------------------------------------------------------

(1 row)

-- check coordinator isn't in metadata
SELECT count(*) != 0 AS "Coordinator is in Metadata"
FROM pg_dist_node
WHERE groupid IN (
    SELECT groupid FROM pg_dist_local_group
);
 Coordinator is in Metadata
---------------------------------------------------------------------
 f
(1 row)

-- run a simple select query and check it also runs in coordinator
SELECT nodeid NOT IN (SELECT nodeid FROM pg_dist_node) AS "Is Coordinator", success, result FROM run_command_on_all_nodes('SELECT 1') ORDER BY 1;
 Is Coordinator | success | result
---------------------------------------------------------------------
 f              | t       | 1
 f              | t       | 1
 t              | t       | 1
(3 rows)

-- check that when coordinator is not in metadata and run_command_on_all_nodes is called from
-- a worker node, command is not run on the coordinator
\c - - - :worker_1_port
SELECT nodeid NOT IN (SELECT nodeid FROM pg_dist_node) AS "Is Coordinator", success, result FROM run_command_on_all_nodes('SELECT 1') ORDER BY 1;
 Is Coordinator | success | result
---------------------------------------------------------------------
 f              | t       | 1
 f              | t       | 1
(2 rows)

\c - - - :master_port
-- create a table
SELECT result FROM run_command_on_all_nodes('CREATE TABLE run_command_on_all_nodes.tbl (a INT)');
    result
---------------------------------------------------------------------
 CREATE TABLE
 CREATE TABLE
 CREATE TABLE
(3 rows)

SELECT tablename FROM pg_tables WHERE schemaname = 'run_command_on_all_nodes';
 tablename
---------------------------------------------------------------------
 tbl
(1 row)

\c - - - :worker_1_port
SELECT tablename FROM pg_tables WHERE schemaname = 'run_command_on_all_nodes';
 tablename
---------------------------------------------------------------------
 tbl
(1 row)

\c - - - :master_port
SET search_path TO run_command_on_all_nodes;
SELECT result FROM run_command_on_all_nodes('SELECT tablename FROM pg_tables WHERE schemaname = ''run_command_on_all_nodes'';');
 result
---------------------------------------------------------------------
 tbl
 tbl
 tbl
(3 rows)

CREATE TABLE test (x int, y int);
SELECT create_distributed_table('test','x');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

-- break a node and check messages
BEGIN;
SELECT nodeid AS worker_1_nodeid FROM pg_dist_node WHERE nodeport = :worker_1_port \gset
UPDATE pg_dist_node SET nodeport = 0 WHERE nodeid = :worker_1_nodeid;
SELECT nodeid = :worker_1_nodeid AS "Is Worker 1", success, result FROM run_command_on_all_nodes('SELECT 1') ORDER BY 1;
 Is Worker 1 | success |              result
---------------------------------------------------------------------
 f           | t       | 1
 f           | t       | 1
 t           | f       | failed to connect to localhost:xxxxx
(3 rows)

SELECT nodeid = :worker_1_nodeid AS "Is Worker 1", success, result FROM run_command_on_all_nodes('SELECT 1', give_warning_for_connection_errors:=true) ORDER BY 1;
WARNING:  Error on node with node id xxxxx: failed to connect to localhost:xxxxx
CONTEXT:  PL/pgSQL function run_command_on_all_nodes(text,boolean,boolean) line XX at RAISE
 Is Worker 1 | success |              result
---------------------------------------------------------------------
 f           | t       | 1
 f           | t       | 1
 t           | f       | failed to connect to localhost:xxxxx
(3 rows)

ROLLBACK;
-- break connection to localhost
BEGIN;
UPDATE pg_dist_node SET nodeport = 0 WHERE groupid = 0;
SELECT success, result
FROM run_command_on_coordinator('SELECT inet_server_port()') ORDER BY 1;
 success | result
---------------------------------------------------------------------
 t       | 57636
(1 row)

SELECT success, result
FROM run_command_on_coordinator('SELECT inet_server_port()', give_warning_for_connection_errors:=true) ORDER BY 1;
 success | result
---------------------------------------------------------------------
 t       | 57636
(1 row)

ROLLBACK;
-- we cannot use run_command_on_coordinator from workers if coordinator is not in the metadata
SELECT success, result FROM run_command_on_all_nodes($$select result from run_command_on_coordinator('select inet_server_port()')$$);
 success |                        result
---------------------------------------------------------------------
 f       | ERROR:  the coordinator is not added to the metadata
 f       | ERROR:  the coordinator is not added to the metadata
 t       | 57636
(3 rows)

-- we can use run_command_on_coordinator from any node if the coordinator is in the metadata
SELECT citus_set_coordinator_host('localhost');
 citus_set_coordinator_host
---------------------------------------------------------------------

(1 row)

SELECT success, result FROM run_command_on_all_nodes($$select result from run_command_on_coordinator('select inet_server_port()')$$);
 success | result
---------------------------------------------------------------------
 t       | 57636
 t       | 57636
 t       | 57636
(3 rows)

SELECT success, result FROM run_command_on_all_nodes($$select result from run_command_on_coordinator('select count(*) from run_command_on_all_nodes.test')$$);
 success | result
---------------------------------------------------------------------
 t       | 0
 t       | 0
 t       | 0
(3 rows)

\c - - - :worker_1_port
-- poor man's DDL from worker
select result from run_command_on_coordinator($$create index on run_command_on_all_nodes.test (x)$$);
    result
---------------------------------------------------------------------
 CREATE INDEX
(1 row)

\c - - - :master_port
-- remove coordinator from metadata to restore pre-test situation
SELECT citus_remove_node(nodename, nodeport) FROM pg_dist_node WHERE groupid = 0;
 citus_remove_node
---------------------------------------------------------------------

(1 row)

-- check that we fail when pg_dist_node is empty
BEGIN;
DELETE FROM pg_dist_node;
SELECT success, result FROM run_command_on_coordinator('select inet_server_port()');
ERROR:  the coordinator is not added to the metadata
HINT:  Add the node as a coordinator by using: SELECT citus_set_coordinator_host('<hostname>')
CONTEXT:  PL/pgSQL function run_command_on_coordinator(text,boolean) line XX at RAISE
ROLLBACK;
-- check that we can do distributed queries from worker nodes
SELECT success, result FROM run_command_on_all_nodes($$insert into run_command_on_all_nodes.test values (1,2)$$, true);
 success |   result
---------------------------------------------------------------------
 t       | INSERT 0 1
 t       | INSERT 0 1
 t       | INSERT 0 1
(3 rows)

SELECT success, result FROM run_command_on_all_nodes($$insert into run_command_on_all_nodes.test values (1,2)$$, false);
 success |   result
---------------------------------------------------------------------
 t       | INSERT 0 1
 t       | INSERT 0 1
 t       | INSERT 0 1
(3 rows)

SELECT success, result FROM run_command_on_all_nodes($$select count(*) from run_command_on_all_nodes.test$$);
 success | result
---------------------------------------------------------------------
 t       | 6
 t       | 6
 t       | 6
(3 rows)

-- ddl commands are only allowed from the coordinator
SELECT success, result FROM run_command_on_all_nodes($$create index on run_command_on_all_nodes.test (x)$$);
 success |                    result
---------------------------------------------------------------------
 f       | ERROR:  operation is not allowed on this node
 f       | ERROR:  operation is not allowed on this node
 t       | CREATE INDEX
(3 rows)

DROP SCHEMA run_command_on_all_nodes CASCADE;
NOTICE:  drop cascades to 2 other objects
DETAIL:  drop cascades to table run_command_on_all_nodes.tbl
drop cascades to table run_command_on_all_nodes.test
SELECT citus_set_coordinator_host('localhost');
 citus_set_coordinator_host
---------------------------------------------------------------------

(1 row)

