mirror of https://github.com/citusdata/citus.git
Disable nonmaindb interface (#7905)
DESCRIPTION: The PR disables the non-main db related features. The non-main db related features were introduced in https://github.com/citusdata/citus/pull/7203.pull/7909/head
parent
711aec80fa
commit
117bd1d04f
|
@ -1834,16 +1834,6 @@ RegisterCitusConfigVariables(void)
|
||||||
GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_UNIT_MS,
|
GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_UNIT_MS,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
DefineCustomStringVariable(
|
|
||||||
"citus.main_db",
|
|
||||||
gettext_noop("Which database is designated as the main_db"),
|
|
||||||
NULL,
|
|
||||||
&MainDb,
|
|
||||||
"",
|
|
||||||
PGC_POSTMASTER,
|
|
||||||
GUC_STANDARD,
|
|
||||||
NULL, NULL, NULL);
|
|
||||||
|
|
||||||
DefineCustomIntVariable(
|
DefineCustomIntVariable(
|
||||||
"citus.max_adaptive_executor_pool_size",
|
"citus.max_adaptive_executor_pool_size",
|
||||||
gettext_noop("Sets the maximum number of connections per worker node used by "
|
gettext_noop("Sets the maximum number of connections per worker node used by "
|
||||||
|
|
|
@ -4,29 +4,21 @@
|
||||||
#include "udfs/citus_internal_database_command/12.2-1.sql"
|
#include "udfs/citus_internal_database_command/12.2-1.sql"
|
||||||
#include "udfs/citus_add_rebalance_strategy/12.2-1.sql"
|
#include "udfs/citus_add_rebalance_strategy/12.2-1.sql"
|
||||||
|
|
||||||
#include "udfs/start_management_transaction/12.2-1.sql"
|
|
||||||
#include "udfs/execute_command_on_remote_nodes_as_user/12.2-1.sql"
|
|
||||||
#include "udfs/mark_object_distributed/12.2-1.sql"
|
|
||||||
DROP FUNCTION pg_catalog.citus_unmark_object_distributed(oid, oid, int);
|
DROP FUNCTION pg_catalog.citus_unmark_object_distributed(oid, oid, int);
|
||||||
#include "udfs/citus_unmark_object_distributed/12.2-1.sql"
|
#include "udfs/citus_unmark_object_distributed/12.2-1.sql"
|
||||||
#include "udfs/commit_management_command_2pc/12.2-1.sql"
|
|
||||||
|
|
||||||
ALTER TABLE pg_catalog.pg_dist_transaction ADD COLUMN outer_xid xid8;
|
ALTER TABLE pg_catalog.pg_dist_transaction ADD COLUMN outer_xid xid8;
|
||||||
|
|
||||||
#include "udfs/citus_internal_acquire_citus_advisory_object_class_lock/12.2-1.sql"
|
#include "udfs/citus_internal_acquire_citus_advisory_object_class_lock/12.2-1.sql"
|
||||||
|
|
||||||
GRANT USAGE ON SCHEMA citus_internal TO PUBLIC;
|
GRANT USAGE ON SCHEMA citus_internal TO PUBLIC;
|
||||||
REVOKE ALL ON FUNCTION citus_internal.commit_management_command_2pc FROM PUBLIC;
|
|
||||||
REVOKE ALL ON FUNCTION citus_internal.execute_command_on_remote_nodes_as_user FROM PUBLIC;
|
|
||||||
REVOKE ALL ON FUNCTION citus_internal.find_groupid_for_node FROM PUBLIC;
|
REVOKE ALL ON FUNCTION citus_internal.find_groupid_for_node FROM PUBLIC;
|
||||||
REVOKE ALL ON FUNCTION citus_internal.mark_object_distributed FROM PUBLIC;
|
|
||||||
REVOKE ALL ON FUNCTION citus_internal.pg_dist_node_trigger_func FROM PUBLIC;
|
REVOKE ALL ON FUNCTION citus_internal.pg_dist_node_trigger_func FROM PUBLIC;
|
||||||
REVOKE ALL ON FUNCTION citus_internal.pg_dist_rebalance_strategy_trigger_func FROM PUBLIC;
|
REVOKE ALL ON FUNCTION citus_internal.pg_dist_rebalance_strategy_trigger_func FROM PUBLIC;
|
||||||
REVOKE ALL ON FUNCTION citus_internal.pg_dist_shard_placement_trigger_func FROM PUBLIC;
|
REVOKE ALL ON FUNCTION citus_internal.pg_dist_shard_placement_trigger_func FROM PUBLIC;
|
||||||
REVOKE ALL ON FUNCTION citus_internal.refresh_isolation_tester_prepared_statement FROM PUBLIC;
|
REVOKE ALL ON FUNCTION citus_internal.refresh_isolation_tester_prepared_statement FROM PUBLIC;
|
||||||
REVOKE ALL ON FUNCTION citus_internal.replace_isolation_tester_func FROM PUBLIC;
|
REVOKE ALL ON FUNCTION citus_internal.replace_isolation_tester_func FROM PUBLIC;
|
||||||
REVOKE ALL ON FUNCTION citus_internal.restore_isolation_tester_func FROM PUBLIC;
|
REVOKE ALL ON FUNCTION citus_internal.restore_isolation_tester_func FROM PUBLIC;
|
||||||
REVOKE ALL ON FUNCTION citus_internal.start_management_transaction FROM PUBLIC;
|
|
||||||
|
|
||||||
#include "udfs/citus_internal_add_colocation_metadata/12.2-1.sql"
|
#include "udfs/citus_internal_add_colocation_metadata/12.2-1.sql"
|
||||||
#include "udfs/citus_internal_add_object_metadata/12.2-1.sql"
|
#include "udfs/citus_internal_add_object_metadata/12.2-1.sql"
|
||||||
|
|
|
@ -5,24 +5,9 @@ DROP FUNCTION citus_internal.acquire_citus_advisory_object_class_lock(int, cstri
|
||||||
|
|
||||||
#include "../udfs/citus_add_rebalance_strategy/10.1-1.sql"
|
#include "../udfs/citus_add_rebalance_strategy/10.1-1.sql"
|
||||||
|
|
||||||
DROP FUNCTION citus_internal.start_management_transaction(
|
|
||||||
outer_xid xid8
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP FUNCTION citus_internal.execute_command_on_remote_nodes_as_user(
|
|
||||||
query text,
|
|
||||||
username text
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP FUNCTION citus_internal.mark_object_distributed(
|
|
||||||
classId Oid, objectName text, objectId Oid, connectionUser text
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP FUNCTION pg_catalog.citus_unmark_object_distributed(oid,oid,int,boolean);
|
DROP FUNCTION pg_catalog.citus_unmark_object_distributed(oid,oid,int,boolean);
|
||||||
#include "../udfs/citus_unmark_object_distributed/10.0-1.sql"
|
#include "../udfs/citus_unmark_object_distributed/10.0-1.sql"
|
||||||
|
|
||||||
DROP FUNCTION citus_internal.commit_management_command_2pc();
|
|
||||||
|
|
||||||
ALTER TABLE pg_catalog.pg_dist_transaction DROP COLUMN outer_xid;
|
ALTER TABLE pg_catalog.pg_dist_transaction DROP COLUMN outer_xid;
|
||||||
REVOKE USAGE ON SCHEMA citus_internal FROM PUBLIC;
|
REVOKE USAGE ON SCHEMA citus_internal FROM PUBLIC;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
CREATE OR REPLACE FUNCTION citus_internal.execute_command_on_remote_nodes_as_user(query text, username text)
|
|
||||||
RETURNS VOID
|
|
||||||
LANGUAGE C
|
|
||||||
AS 'MODULE_PATHNAME', $$execute_command_on_remote_nodes_as_user$$;
|
|
||||||
|
|
||||||
COMMENT ON FUNCTION citus_internal.execute_command_on_remote_nodes_as_user(query text, username text)
|
|
||||||
IS 'executes a query on the nodes other than the current one';
|
|
|
@ -1,7 +0,0 @@
|
||||||
CREATE OR REPLACE FUNCTION citus_internal.execute_command_on_remote_nodes_as_user(query text, username text)
|
|
||||||
RETURNS VOID
|
|
||||||
LANGUAGE C
|
|
||||||
AS 'MODULE_PATHNAME', $$execute_command_on_remote_nodes_as_user$$;
|
|
||||||
|
|
||||||
COMMENT ON FUNCTION citus_internal.execute_command_on_remote_nodes_as_user(query text, username text)
|
|
||||||
IS 'executes a query on the nodes other than the current one';
|
|
|
@ -1,7 +0,0 @@
|
||||||
CREATE OR REPLACE FUNCTION citus_internal.mark_object_distributed(classId Oid, objectName text, objectId Oid, connectionUser text)
|
|
||||||
RETURNS VOID
|
|
||||||
LANGUAGE C
|
|
||||||
AS 'MODULE_PATHNAME', $$mark_object_distributed$$;
|
|
||||||
|
|
||||||
COMMENT ON FUNCTION citus_internal.mark_object_distributed(classId Oid, objectName text, objectId Oid, connectionUser text)
|
|
||||||
IS 'adds an object to pg_dist_object on all nodes';
|
|
|
@ -1,7 +0,0 @@
|
||||||
CREATE OR REPLACE FUNCTION citus_internal.mark_object_distributed(classId Oid, objectName text, objectId Oid, connectionUser text)
|
|
||||||
RETURNS VOID
|
|
||||||
LANGUAGE C
|
|
||||||
AS 'MODULE_PATHNAME', $$mark_object_distributed$$;
|
|
||||||
|
|
||||||
COMMENT ON FUNCTION citus_internal.mark_object_distributed(classId Oid, objectName text, objectId Oid, connectionUser text)
|
|
||||||
IS 'adds an object to pg_dist_object on all nodes';
|
|
|
@ -1,7 +0,0 @@
|
||||||
CREATE OR REPLACE FUNCTION citus_internal.start_management_transaction(outer_xid xid8)
|
|
||||||
RETURNS VOID
|
|
||||||
LANGUAGE C
|
|
||||||
AS 'MODULE_PATHNAME', $$start_management_transaction$$;
|
|
||||||
|
|
||||||
COMMENT ON FUNCTION citus_internal.start_management_transaction(outer_xid xid8)
|
|
||||||
IS 'internal Citus function that starts a management transaction in the main database';
|
|
|
@ -1,7 +0,0 @@
|
||||||
CREATE OR REPLACE FUNCTION citus_internal.start_management_transaction(outer_xid xid8)
|
|
||||||
RETURNS VOID
|
|
||||||
LANGUAGE C
|
|
||||||
AS 'MODULE_PATHNAME', $$start_management_transaction$$;
|
|
||||||
|
|
||||||
COMMENT ON FUNCTION citus_internal.start_management_transaction(outer_xid xid8)
|
|
||||||
IS 'internal Citus function that starts a management transaction in the main database';
|
|
|
@ -1,74 +0,0 @@
|
||||||
# This test checks that once citus.main_db is set and the
|
|
||||||
# server is restarted. A Citus Maintenance Daemon for the main_db
|
|
||||||
# is launched. This should happen even if there is no query run
|
|
||||||
# in main_db yet.
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def wait_until_maintenance_deamons_start(deamoncount, cluster):
|
|
||||||
i = 0
|
|
||||||
n = 0
|
|
||||||
|
|
||||||
while i < 10:
|
|
||||||
i += 1
|
|
||||||
n = cluster.coordinator.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon';"
|
|
||||||
)
|
|
||||||
|
|
||||||
if n == deamoncount:
|
|
||||||
break
|
|
||||||
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
assert n == deamoncount
|
|
||||||
|
|
||||||
|
|
||||||
def test_set_maindb(cluster_factory):
|
|
||||||
cluster = cluster_factory(0)
|
|
||||||
|
|
||||||
# Test that once citus.main_db is set to a database name
|
|
||||||
# there are two maintenance deamons running upon restart.
|
|
||||||
# One maintenance deamon for the database of the current connection
|
|
||||||
# and one for the citus.main_db.
|
|
||||||
cluster.coordinator.create_database("mymaindb")
|
|
||||||
cluster.coordinator.configure("citus.main_db='mymaindb'")
|
|
||||||
cluster.coordinator.restart()
|
|
||||||
|
|
||||||
assert cluster.coordinator.sql_value("SHOW citus.main_db;") == "mymaindb"
|
|
||||||
|
|
||||||
wait_until_maintenance_deamons_start(2, cluster)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
cluster.coordinator.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon' AND datname='mymaindb';"
|
|
||||||
)
|
|
||||||
== 1
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test that once citus.main_db is set to empty string
|
|
||||||
# there is only one maintenance deamon for the database
|
|
||||||
# of the current connection.
|
|
||||||
cluster.coordinator.configure("citus.main_db=''")
|
|
||||||
cluster.coordinator.restart()
|
|
||||||
assert cluster.coordinator.sql_value("SHOW citus.main_db;") == ""
|
|
||||||
|
|
||||||
wait_until_maintenance_deamons_start(1, cluster)
|
|
||||||
|
|
||||||
# Test that after citus.main_db is dropped. The maintenance
|
|
||||||
# deamon for this database is terminated.
|
|
||||||
cluster.coordinator.configure("citus.main_db='mymaindb'")
|
|
||||||
cluster.coordinator.restart()
|
|
||||||
assert cluster.coordinator.sql_value("SHOW citus.main_db;") == "mymaindb"
|
|
||||||
|
|
||||||
wait_until_maintenance_deamons_start(2, cluster)
|
|
||||||
|
|
||||||
cluster.coordinator.sql("DROP DATABASE mymaindb;")
|
|
||||||
|
|
||||||
wait_until_maintenance_deamons_start(1, cluster)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
cluster.coordinator.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon' AND datname='mymaindb';"
|
|
||||||
)
|
|
||||||
== 0
|
|
||||||
)
|
|
|
@ -1,198 +0,0 @@
|
||||||
def test_main_commited_outer_not_yet(cluster):
|
|
||||||
c = cluster.coordinator
|
|
||||||
w0 = cluster.workers[0]
|
|
||||||
|
|
||||||
# create a non-main database
|
|
||||||
c.sql("CREATE DATABASE db1")
|
|
||||||
|
|
||||||
# we will use cur1 to simulate non-main database user and
|
|
||||||
# cur2 to manually do the steps we would do in the main database
|
|
||||||
with c.cur(dbname="db1") as cur1, c.cur() as cur2:
|
|
||||||
# let's start a transaction and find its transaction id
|
|
||||||
cur1.execute("BEGIN")
|
|
||||||
cur1.execute("SELECT txid_current()")
|
|
||||||
txid = cur1.fetchall()
|
|
||||||
|
|
||||||
# using the transaction id of the cur1 simulate the main database commands manually
|
|
||||||
cur2.execute("BEGIN")
|
|
||||||
cur2.execute(
|
|
||||||
"SELECT citus_internal.start_management_transaction(%s)", (str(txid[0][0]),)
|
|
||||||
)
|
|
||||||
cur2.execute(
|
|
||||||
"SELECT citus_internal.execute_command_on_remote_nodes_as_user('CREATE USER u1;', 'postgres')"
|
|
||||||
)
|
|
||||||
cur2.execute(
|
|
||||||
"SELECT citus_internal.mark_object_distributed(1260, 'u1', 123123, 'postgres')"
|
|
||||||
)
|
|
||||||
cur2.execute("COMMIT")
|
|
||||||
|
|
||||||
# run the transaction recovery
|
|
||||||
c.sql("SELECT recover_prepared_transactions()")
|
|
||||||
|
|
||||||
# user should not be created on the worker because outer transaction is not committed yet
|
|
||||||
role_before_commit = w0.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_roles WHERE rolname = 'u1'"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(role_before_commit) == 0
|
|
||||||
), "role is in pg_dist_object despite not committing"
|
|
||||||
|
|
||||||
# user should not be in pg_dist_object on the coordinator because outer transaction is not committed yet
|
|
||||||
pdo_coordinator_before_commit = c.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_dist_object WHERE objid = 123123"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(pdo_coordinator_before_commit) == 0
|
|
||||||
), "role is in pg_dist_object on coordinator despite not committing"
|
|
||||||
|
|
||||||
# user should not be in pg_dist_object on the worker because outer transaction is not committed yet
|
|
||||||
pdo_worker_before_commit = w0.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_dist_object WHERE objid::regrole::text = 'u1'"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(pdo_worker_before_commit) == 0
|
|
||||||
), "role is in pg_dist_object on worker despite not committing"
|
|
||||||
|
|
||||||
# commit in cur1 so the transaction recovery thinks this is a successful transaction
|
|
||||||
cur1.execute("COMMIT")
|
|
||||||
|
|
||||||
# run the transaction recovery again after committing
|
|
||||||
c.sql("SELECT recover_prepared_transactions()")
|
|
||||||
|
|
||||||
# check that the user is created by the transaction recovery on the worker
|
|
||||||
role_after_commit = w0.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_roles WHERE rolname = 'u1'"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(role_after_commit) == 1
|
|
||||||
), "role is not created during recovery despite committing"
|
|
||||||
|
|
||||||
# check that the user is in pg_dist_object on the coordinator after transaction recovery
|
|
||||||
pdo_coordinator_after_commit = c.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_dist_object WHERE objid = 123123"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(pdo_coordinator_after_commit) == 1
|
|
||||||
), "role is not in pg_dist_object on coordinator after recovery despite committing"
|
|
||||||
|
|
||||||
# check that the user is in pg_dist_object on the worker after transaction recovery
|
|
||||||
pdo_worker_after_commit = w0.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_dist_object WHERE objid::regrole::text = 'u1'"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(pdo_worker_after_commit) == 1
|
|
||||||
), "role is not in pg_dist_object on worker after recovery despite committing"
|
|
||||||
|
|
||||||
c.sql("DROP DATABASE db1")
|
|
||||||
c.sql(
|
|
||||||
"SELECT citus_internal.execute_command_on_remote_nodes_as_user('DROP USER u1', 'postgres')"
|
|
||||||
)
|
|
||||||
c.sql(
|
|
||||||
"""
|
|
||||||
SELECT run_command_on_workers($$
|
|
||||||
DELETE FROM pg_dist_object
|
|
||||||
WHERE objid::regrole::text = 'u1'
|
|
||||||
$$)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
c.sql(
|
|
||||||
"""
|
|
||||||
DELETE FROM pg_dist_object
|
|
||||||
WHERE objid = 123123
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_main_commited_outer_aborted(cluster):
|
|
||||||
c = cluster.coordinator
|
|
||||||
w0 = cluster.workers[0]
|
|
||||||
|
|
||||||
# create a non-main database
|
|
||||||
c.sql("CREATE DATABASE db2")
|
|
||||||
|
|
||||||
# we will use cur1 to simulate non-main database user and
|
|
||||||
# cur2 to manually do the steps we would do in the main database
|
|
||||||
with c.cur(dbname="db2") as cur1, c.cur() as cur2:
|
|
||||||
# let's start a transaction and find its transaction id
|
|
||||||
cur1.execute("BEGIN")
|
|
||||||
cur1.execute("SELECT txid_current()")
|
|
||||||
txid = cur1.fetchall()
|
|
||||||
|
|
||||||
# using the transaction id of the cur1 simulate the main database commands manually
|
|
||||||
cur2.execute("BEGIN")
|
|
||||||
cur2.execute(
|
|
||||||
"SELECT citus_internal.start_management_transaction(%s)", (str(txid[0][0]),)
|
|
||||||
)
|
|
||||||
cur2.execute(
|
|
||||||
"SELECT citus_internal.execute_command_on_remote_nodes_as_user('CREATE USER u2;', 'postgres')"
|
|
||||||
)
|
|
||||||
cur2.execute(
|
|
||||||
"SELECT citus_internal.mark_object_distributed(1260, 'u2', 321321, 'postgres')"
|
|
||||||
)
|
|
||||||
cur2.execute("COMMIT")
|
|
||||||
|
|
||||||
# abort cur1 so the transaction recovery thinks this is an aborted transaction
|
|
||||||
cur1.execute("ABORT")
|
|
||||||
|
|
||||||
# check that the user is not yet created on the worker
|
|
||||||
role_before_recovery = w0.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_roles WHERE rolname = 'u2'"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert int(role_before_recovery) == 0, "role is already created before recovery"
|
|
||||||
|
|
||||||
# check that the user is not in pg_dist_object on the coordinator
|
|
||||||
pdo_coordinator_before_recovery = c.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_dist_object WHERE objid = 321321"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(pdo_coordinator_before_recovery) == 0
|
|
||||||
), "role is already in pg_dist_object on coordinator before recovery"
|
|
||||||
|
|
||||||
# check that the user is not in pg_dist_object on the worker
|
|
||||||
pdo_worker_before_recovery = w0.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_dist_object WHERE objid::regrole::text = 'u2'"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(pdo_worker_before_recovery) == 0
|
|
||||||
), "role is already in pg_dist_object on worker before recovery"
|
|
||||||
|
|
||||||
# run the transaction recovery
|
|
||||||
c.sql("SELECT recover_prepared_transactions()")
|
|
||||||
|
|
||||||
# check that the user is not created by the transaction recovery on the worker
|
|
||||||
role_after_recovery = w0.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_roles WHERE rolname = 'u2'"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(role_after_recovery) == 0
|
|
||||||
), "role is created during recovery despite aborting"
|
|
||||||
|
|
||||||
# check that the user is not in pg_dist_object on the coordinator after transaction recovery
|
|
||||||
pdo_coordinator_after_recovery = c.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_dist_object WHERE objid = 321321"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(pdo_coordinator_after_recovery) == 0
|
|
||||||
), "role is in pg_dist_object on coordinator after recovery despite aborting"
|
|
||||||
|
|
||||||
# check that the user is not in pg_dist_object on the worker after transaction recovery
|
|
||||||
pdo_worker_after_recovery = w0.sql_value(
|
|
||||||
"SELECT count(*) FROM pg_dist_object WHERE objid::regrole::text = 'u2'"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
int(pdo_worker_after_recovery) == 0
|
|
||||||
), "role is in pg_dist_object on worker after recovery despite aborting"
|
|
||||||
|
|
||||||
c.sql("DROP DATABASE db2")
|
|
|
@ -2,8 +2,6 @@
|
||||||
CREATE USER nonsuperuser CREATEROLE;
|
CREATE USER nonsuperuser CREATEROLE;
|
||||||
SET ROLE nonsuperuser;
|
SET ROLE nonsuperuser;
|
||||||
--- The non-superuser role should not be able to access citus_internal functions
|
--- The non-superuser role should not be able to access citus_internal functions
|
||||||
SELECT citus_internal.commit_management_command_2pc();
|
|
||||||
ERROR: permission denied for function commit_management_command_2pc
|
|
||||||
SELECT citus_internal.replace_isolation_tester_func();
|
SELECT citus_internal.replace_isolation_tester_func();
|
||||||
ERROR: permission denied for function replace_isolation_tester_func
|
ERROR: permission denied for function replace_isolation_tester_func
|
||||||
RESET ROLE;
|
RESET ROLE;
|
||||||
|
|
|
@ -78,11 +78,5 @@ SELECT * FROM public.check_database_on_all_nodes('test_locale_provider') ORDER B
|
||||||
worker node (remote) | {"database_properties": {"datacl": null, "datname": "test_locale_provider", "datctype": "C", "encoding": "UTF8", "datcollate": "C", "tablespace": "pg_default", "daticurules": null, "datallowconn": true, "datconnlimit": -1, "daticulocale": null, "datistemplate": false, "database_owner": "postgres", "datcollversion": null, "datlocprovider": "c"}, "pg_dist_object_record_for_db_exists": true, "stale_pg_dist_object_record_for_a_db_exists": false}
|
worker node (remote) | {"database_properties": {"datacl": null, "datname": "test_locale_provider", "datctype": "C", "encoding": "UTF8", "datcollate": "C", "tablespace": "pg_default", "daticurules": null, "datallowconn": true, "datconnlimit": -1, "daticulocale": null, "datistemplate": false, "database_owner": "postgres", "datcollversion": null, "datlocprovider": "c"}, "pg_dist_object_record_for_db_exists": true, "stale_pg_dist_object_record_for_a_db_exists": false}
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
\c test_locale_provider - - :worker_2_port
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
create database unsupported_option_from_non_main_db with oid = 12345;
|
|
||||||
ERROR: CREATE DATABASE option "oid" is not supported
|
|
||||||
\c regression - - :master_port
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
drop database test_locale_provider;
|
drop database test_locale_provider;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
|
|
@ -1431,20 +1431,16 @@ SELECT * FROM multi_extension.print_extension_changes();
|
||||||
| function citus_internal.add_shard_metadata(regclass,bigint,"char",text,text) void
|
| function citus_internal.add_shard_metadata(regclass,bigint,"char",text,text) void
|
||||||
| function citus_internal.add_tenant_schema(oid,integer) void
|
| function citus_internal.add_tenant_schema(oid,integer) void
|
||||||
| function citus_internal.adjust_local_clock_to_remote(cluster_clock) void
|
| function citus_internal.adjust_local_clock_to_remote(cluster_clock) void
|
||||||
| function citus_internal.commit_management_command_2pc() void
|
|
||||||
| function citus_internal.database_command(text) void
|
| function citus_internal.database_command(text) void
|
||||||
| function citus_internal.delete_colocation_metadata(integer) void
|
| function citus_internal.delete_colocation_metadata(integer) void
|
||||||
| function citus_internal.delete_partition_metadata(regclass) void
|
| function citus_internal.delete_partition_metadata(regclass) void
|
||||||
| function citus_internal.delete_placement_metadata(bigint) void
|
| function citus_internal.delete_placement_metadata(bigint) void
|
||||||
| function citus_internal.delete_shard_metadata(bigint) void
|
| function citus_internal.delete_shard_metadata(bigint) void
|
||||||
| function citus_internal.delete_tenant_schema(oid) void
|
| function citus_internal.delete_tenant_schema(oid) void
|
||||||
| function citus_internal.execute_command_on_remote_nodes_as_user(text,text) void
|
|
||||||
| function citus_internal.global_blocked_processes() SETOF record
|
| function citus_internal.global_blocked_processes() SETOF record
|
||||||
| function citus_internal.is_replication_origin_tracking_active() boolean
|
| function citus_internal.is_replication_origin_tracking_active() boolean
|
||||||
| function citus_internal.local_blocked_processes() SETOF record
|
| function citus_internal.local_blocked_processes() SETOF record
|
||||||
| function citus_internal.mark_node_not_synced(integer,integer) void
|
| function citus_internal.mark_node_not_synced(integer,integer) void
|
||||||
| function citus_internal.mark_object_distributed(oid,text,oid,text) void
|
|
||||||
| function citus_internal.start_management_transaction(xid8) void
|
|
||||||
| function citus_internal.start_replication_origin_tracking() void
|
| function citus_internal.start_replication_origin_tracking() void
|
||||||
| function citus_internal.stop_replication_origin_tracking() void
|
| function citus_internal.stop_replication_origin_tracking() void
|
||||||
| function citus_internal.unregister_tenant_schema_globally(oid,text) void
|
| function citus_internal.unregister_tenant_schema_globally(oid,text) void
|
||||||
|
@ -1452,7 +1448,7 @@ SELECT * FROM multi_extension.print_extension_changes();
|
||||||
| function citus_internal.update_placement_metadata(bigint,integer,integer) void
|
| function citus_internal.update_placement_metadata(bigint,integer,integer) void
|
||||||
| function citus_internal.update_relation_colocation(oid,integer) void
|
| function citus_internal.update_relation_colocation(oid,integer) void
|
||||||
| function citus_unmark_object_distributed(oid,oid,integer,boolean) void
|
| function citus_unmark_object_distributed(oid,oid,integer,boolean) void
|
||||||
(30 rows)
|
(26 rows)
|
||||||
|
|
||||||
DROP TABLE multi_extension.prev_objects, multi_extension.extension_diff;
|
DROP TABLE multi_extension.prev_objects, multi_extension.extension_diff;
|
||||||
-- show running version
|
-- show running version
|
||||||
|
|
|
@ -64,27 +64,23 @@ ORDER BY 1;
|
||||||
function citus_internal.add_shard_metadata(regclass,bigint,"char",text,text)
|
function citus_internal.add_shard_metadata(regclass,bigint,"char",text,text)
|
||||||
function citus_internal.add_tenant_schema(oid,integer)
|
function citus_internal.add_tenant_schema(oid,integer)
|
||||||
function citus_internal.adjust_local_clock_to_remote(cluster_clock)
|
function citus_internal.adjust_local_clock_to_remote(cluster_clock)
|
||||||
function citus_internal.commit_management_command_2pc()
|
|
||||||
function citus_internal.database_command(text)
|
function citus_internal.database_command(text)
|
||||||
function citus_internal.delete_colocation_metadata(integer)
|
function citus_internal.delete_colocation_metadata(integer)
|
||||||
function citus_internal.delete_partition_metadata(regclass)
|
function citus_internal.delete_partition_metadata(regclass)
|
||||||
function citus_internal.delete_placement_metadata(bigint)
|
function citus_internal.delete_placement_metadata(bigint)
|
||||||
function citus_internal.delete_shard_metadata(bigint)
|
function citus_internal.delete_shard_metadata(bigint)
|
||||||
function citus_internal.delete_tenant_schema(oid)
|
function citus_internal.delete_tenant_schema(oid)
|
||||||
function citus_internal.execute_command_on_remote_nodes_as_user(text,text)
|
|
||||||
function citus_internal.find_groupid_for_node(text,integer)
|
function citus_internal.find_groupid_for_node(text,integer)
|
||||||
function citus_internal.global_blocked_processes()
|
function citus_internal.global_blocked_processes()
|
||||||
function citus_internal.is_replication_origin_tracking_active()
|
function citus_internal.is_replication_origin_tracking_active()
|
||||||
function citus_internal.local_blocked_processes()
|
function citus_internal.local_blocked_processes()
|
||||||
function citus_internal.mark_node_not_synced(integer,integer)
|
function citus_internal.mark_node_not_synced(integer,integer)
|
||||||
function citus_internal.mark_object_distributed(oid,text,oid,text)
|
|
||||||
function citus_internal.pg_dist_node_trigger_func()
|
function citus_internal.pg_dist_node_trigger_func()
|
||||||
function citus_internal.pg_dist_rebalance_strategy_trigger_func()
|
function citus_internal.pg_dist_rebalance_strategy_trigger_func()
|
||||||
function citus_internal.pg_dist_shard_placement_trigger_func()
|
function citus_internal.pg_dist_shard_placement_trigger_func()
|
||||||
function citus_internal.refresh_isolation_tester_prepared_statement()
|
function citus_internal.refresh_isolation_tester_prepared_statement()
|
||||||
function citus_internal.replace_isolation_tester_func()
|
function citus_internal.replace_isolation_tester_func()
|
||||||
function citus_internal.restore_isolation_tester_func()
|
function citus_internal.restore_isolation_tester_func()
|
||||||
function citus_internal.start_management_transaction(xid8)
|
|
||||||
function citus_internal.start_replication_origin_tracking()
|
function citus_internal.start_replication_origin_tracking()
|
||||||
function citus_internal.stop_replication_origin_tracking()
|
function citus_internal.stop_replication_origin_tracking()
|
||||||
function citus_internal.unregister_tenant_schema_globally(oid,text)
|
function citus_internal.unregister_tenant_schema_globally(oid,text)
|
||||||
|
@ -371,5 +367,5 @@ ORDER BY 1;
|
||||||
view citus_stat_tenants_local
|
view citus_stat_tenants_local
|
||||||
view pg_dist_shard_placement
|
view pg_dist_shard_placement
|
||||||
view time_partitions
|
view time_partitions
|
||||||
(361 rows)
|
(357 rows)
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ test: failure_multi_row_insert
|
||||||
test: failure_mx_metadata_sync
|
test: failure_mx_metadata_sync
|
||||||
test: failure_mx_metadata_sync_multi_trans
|
test: failure_mx_metadata_sync_multi_trans
|
||||||
test: failure_connection_establishment
|
test: failure_connection_establishment
|
||||||
test: failure_non_main_db_2pc
|
|
||||||
test: failure_create_database
|
test: failure_create_database
|
||||||
|
|
||||||
# this test syncs metadata to the workers
|
# this test syncs metadata to the workers
|
||||||
|
|
|
@ -40,7 +40,6 @@ test: create_drop_database_propagation_pg15
|
||||||
test: create_drop_database_propagation_pg16
|
test: create_drop_database_propagation_pg16
|
||||||
test: comment_on_database
|
test: comment_on_database
|
||||||
test: comment_on_role
|
test: comment_on_role
|
||||||
test: metadata_sync_from_non_maindb
|
|
||||||
# don't parallelize single_shard_table_udfs to make sure colocation ids are sequential
|
# don't parallelize single_shard_table_udfs to make sure colocation ids are sequential
|
||||||
test: single_shard_table_udfs
|
test: single_shard_table_udfs
|
||||||
test: schema_based_sharding
|
test: schema_based_sharding
|
||||||
|
@ -58,7 +57,7 @@ test: multi_metadata_attributes
|
||||||
|
|
||||||
test: multi_read_from_secondaries
|
test: multi_read_from_secondaries
|
||||||
|
|
||||||
test: grant_on_database_propagation grant_on_database_propagation_from_non_maindb
|
test: grant_on_database_propagation
|
||||||
test: alter_database_propagation
|
test: alter_database_propagation
|
||||||
|
|
||||||
test: citus_shards
|
test: citus_shards
|
||||||
|
|
|
@ -108,7 +108,6 @@ test: object_propagation_debug
|
||||||
test: undistribute_table
|
test: undistribute_table
|
||||||
test: run_command_on_all_nodes
|
test: run_command_on_all_nodes
|
||||||
test: background_task_queue_monitor
|
test: background_task_queue_monitor
|
||||||
test: other_databases grant_role_from_non_maindb role_operations_from_non_maindb seclabel_non_maindb
|
|
||||||
test: citus_internal_access
|
test: citus_internal_access
|
||||||
test: function_with_case_when
|
test: function_with_case_when
|
||||||
|
|
||||||
|
|
|
@ -492,7 +492,6 @@ push(@pgOptions, "citus.stat_statements_track = 'all'");
|
||||||
push(@pgOptions, "citus.enable_change_data_capture=on");
|
push(@pgOptions, "citus.enable_change_data_capture=on");
|
||||||
push(@pgOptions, "citus.stat_tenants_limit = 2");
|
push(@pgOptions, "citus.stat_tenants_limit = 2");
|
||||||
push(@pgOptions, "citus.stat_tenants_track = 'ALL'");
|
push(@pgOptions, "citus.stat_tenants_track = 'ALL'");
|
||||||
push(@pgOptions, "citus.main_db = 'regression'");
|
|
||||||
push(@pgOptions, "citus.superuser = 'postgres'");
|
push(@pgOptions, "citus.superuser = 'postgres'");
|
||||||
|
|
||||||
# Some tests look at shards in pg_class, make sure we can usually see them:
|
# Some tests look at shards in pg_class, make sure we can usually see them:
|
||||||
|
|
|
@ -3,7 +3,6 @@ CREATE USER nonsuperuser CREATEROLE;
|
||||||
|
|
||||||
SET ROLE nonsuperuser;
|
SET ROLE nonsuperuser;
|
||||||
--- The non-superuser role should not be able to access citus_internal functions
|
--- The non-superuser role should not be able to access citus_internal functions
|
||||||
SELECT citus_internal.commit_management_command_2pc();
|
|
||||||
SELECT citus_internal.replace_isolation_tester_func();
|
SELECT citus_internal.replace_isolation_tester_func();
|
||||||
|
|
||||||
RESET ROLE;
|
RESET ROLE;
|
||||||
|
|
|
@ -60,14 +60,6 @@ CREATE DATABASE test_locale_provider
|
||||||
|
|
||||||
SELECT * FROM public.check_database_on_all_nodes('test_locale_provider') ORDER BY node_type;
|
SELECT * FROM public.check_database_on_all_nodes('test_locale_provider') ORDER BY node_type;
|
||||||
|
|
||||||
\c test_locale_provider - - :worker_2_port
|
|
||||||
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
create database unsupported_option_from_non_main_db with oid = 12345;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
drop database test_locale_provider;
|
drop database test_locale_provider;
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
|
||||||
|
|
||||||
CREATE SCHEMA failure_non_main_db_2pc;
|
|
||||||
SET SEARCH_PATH TO 'failure_non_main_db_2pc';
|
|
||||||
|
|
||||||
CREATE DATABASE other_db1;
|
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="COMMIT PREPARED").kill()');
|
|
||||||
|
|
||||||
\c other_db1
|
|
||||||
|
|
||||||
CREATE USER user_1;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
|
||||||
|
|
||||||
SELECT nodeid, result FROM run_command_on_all_nodes($$SELECT rolname FROM pg_roles WHERE rolname::TEXT = 'user_1'$$) ORDER BY 1;
|
|
||||||
|
|
||||||
SELECT recover_prepared_transactions();
|
|
||||||
|
|
||||||
SELECT nodeid, result FROM run_command_on_all_nodes($$SELECT rolname FROM pg_roles WHERE rolname::TEXT = 'user_1'$$) ORDER BY 1;
|
|
||||||
|
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="CREATE USER user_2").kill()');
|
|
||||||
|
|
||||||
\c other_db1
|
|
||||||
|
|
||||||
CREATE USER user_2;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
|
||||||
|
|
||||||
SELECT nodeid, result FROM run_command_on_all_nodes($$SELECT rolname FROM pg_roles WHERE rolname::TEXT = 'user_2'$$) ORDER BY 1;
|
|
||||||
|
|
||||||
SELECT recover_prepared_transactions();
|
|
||||||
|
|
||||||
SELECT nodeid, result FROM run_command_on_all_nodes($$SELECT rolname FROM pg_roles WHERE rolname::TEXT = 'user_2'$$) ORDER BY 1;
|
|
||||||
|
|
||||||
DROP DATABASE other_db1;
|
|
||||||
-- user_2 should not exist because the query to create it will fail
|
|
||||||
-- but let's make sure we try to drop it just in case
|
|
||||||
DROP USER IF EXISTS user_1, user_2;
|
|
||||||
|
|
||||||
SELECT citus_set_coordinator_host('localhost');
|
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
|
|
||||||
CREATE DATABASE other_db2;
|
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="COMMIT PREPARED").kill()');
|
|
||||||
|
|
||||||
\c other_db2
|
|
||||||
|
|
||||||
CREATE USER user_3;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
|
||||||
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$SELECT rolname FROM pg_roles WHERE rolname::TEXT = 'user_3'$$) ORDER BY 1;
|
|
||||||
|
|
||||||
SELECT recover_prepared_transactions();
|
|
||||||
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$SELECT rolname FROM pg_roles WHERE rolname::TEXT = 'user_3'$$) ORDER BY 1;
|
|
||||||
|
|
||||||
DROP DATABASE other_db2;
|
|
||||||
DROP USER user_3;
|
|
||||||
|
|
||||||
\c - - - :master_port
|
|
||||||
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$DELETE FROM pg_dist_node WHERE groupid = 0$$);
|
|
||||||
|
|
||||||
DROP SCHEMA failure_non_main_db_2pc;
|
|
|
@ -1,246 +0,0 @@
|
||||||
-- Public role has connect,temp,temporary privileges on database
|
|
||||||
-- To test these scenarios, we need to revoke these privileges from public role
|
|
||||||
-- since public role privileges are inherited by new roles/users
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
create database test_2pc_db;
|
|
||||||
show citus.main_db;
|
|
||||||
revoke connect,temp,temporary on database test_2pc_db from public;
|
|
||||||
|
|
||||||
CREATE SCHEMA grant_on_database_propagation_non_maindb;
|
|
||||||
SET search_path TO grant_on_database_propagation_non_maindb;
|
|
||||||
|
|
||||||
-- test grant/revoke CREATE privilege propagation on database
|
|
||||||
create user "myuser'_test";
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
grant create on database test_2pc_db to "myuser'_test";
|
|
||||||
|
|
||||||
\c regression - - :master_port;
|
|
||||||
select check_database_privileges('myuser''_test','test_2pc_db',ARRAY['CREATE']);
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
revoke create on database test_2pc_db from "myuser'_test";
|
|
||||||
|
|
||||||
\c regression - - :master_port;
|
|
||||||
select check_database_privileges('myuser''_test','test_2pc_db',ARRAY['CREATE']);
|
|
||||||
|
|
||||||
drop user "myuser'_test";
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- test grant/revoke CONNECT privilege propagation on database
|
|
||||||
\c regression - - :master_port
|
|
||||||
create user myuser2;
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
grant CONNECT on database test_2pc_db to myuser2;
|
|
||||||
|
|
||||||
\c regression - - :master_port;
|
|
||||||
select check_database_privileges('myuser2','test_2pc_db',ARRAY['CONNECT']);
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
revoke connect on database test_2pc_db from myuser2;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser2','test_2pc_db',ARRAY['CONNECT']);
|
|
||||||
|
|
||||||
drop user myuser2;
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- test grant/revoke TEMP privilege propagation on database
|
|
||||||
\c regression - - :master_port
|
|
||||||
create user myuser3;
|
|
||||||
|
|
||||||
-- test grant/revoke temp on database
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
grant TEMP on database test_2pc_db to myuser3;
|
|
||||||
|
|
||||||
\c regression - - :master_port;
|
|
||||||
select check_database_privileges('myuser3','test_2pc_db',ARRAY['TEMP']);
|
|
||||||
|
|
||||||
|
|
||||||
\c test_2pc_db - - :worker_1_port
|
|
||||||
revoke TEMP on database test_2pc_db from myuser3;
|
|
||||||
|
|
||||||
\c regression - - :master_port;
|
|
||||||
select check_database_privileges('myuser3','test_2pc_db',ARRAY['TEMP']);
|
|
||||||
|
|
||||||
drop user myuser3;
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
-- test temporary privilege on database
|
|
||||||
create user myuser4;
|
|
||||||
|
|
||||||
-- test grant/revoke temporary on database
|
|
||||||
\c test_2pc_db - - :worker_1_port
|
|
||||||
grant TEMPORARY on database test_2pc_db to myuser4;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser4','test_2pc_db',ARRAY['TEMPORARY']);
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
revoke TEMPORARY on database test_2pc_db from myuser4;
|
|
||||||
|
|
||||||
\c regression - - :master_port;
|
|
||||||
select check_database_privileges('myuser4','test_2pc_db',ARRAY['TEMPORARY']);
|
|
||||||
|
|
||||||
drop user myuser4;
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- test ALL privileges with ALL statement on database
|
|
||||||
create user myuser5;
|
|
||||||
|
|
||||||
grant ALL on database test_2pc_db to myuser5;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser5','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
revoke ALL on database test_2pc_db from myuser5;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser5','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
|
|
||||||
drop user myuser5;
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- test CREATE,CONNECT,TEMP,TEMPORARY privileges one by one on database
|
|
||||||
create user myuser6;
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
grant CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db to myuser6;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser6','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
revoke CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db from myuser6;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser6','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
|
|
||||||
|
|
||||||
drop user myuser6;
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- test CREATE,CONNECT,TEMP,TEMPORARY privileges one by one on database with grant option
|
|
||||||
create user myuser7;
|
|
||||||
create user myuser_1;
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
grant CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db to myuser7;
|
|
||||||
|
|
||||||
set role myuser7;
|
|
||||||
--here since myuser7 does not have grant option, it should fail
|
|
||||||
grant CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db to myuser_1;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser_1','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
|
|
||||||
grant CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db to myuser7 with grant option;
|
|
||||||
set role myuser7;
|
|
||||||
|
|
||||||
--here since myuser have grant option, it should succeed
|
|
||||||
grant CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db to myuser_1 granted by myuser7;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser_1','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
|
|
||||||
--below test should fail and should throw an error since myuser_1 still have the dependent privileges
|
|
||||||
revoke CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db from myuser7 restrict;
|
|
||||||
--below test should fail and should throw an error since myuser_1 still have the dependent privileges
|
|
||||||
revoke grant option for CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db from myuser7 restrict ;
|
|
||||||
|
|
||||||
--below test should succeed and should not throw any error since myuser_1 privileges are revoked with cascade
|
|
||||||
revoke grant option for CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db from myuser7 cascade ;
|
|
||||||
|
|
||||||
--here we test if myuser7 still have the privileges after revoke grant option for
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser7','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
|
|
||||||
reset role;
|
|
||||||
|
|
||||||
revoke CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db from myuser7;
|
|
||||||
revoke CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db from myuser_1;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
drop user myuser_1;
|
|
||||||
drop user myuser7;
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- test CREATE,CONNECT,TEMP,TEMPORARY privileges one by one on database multi database
|
|
||||||
-- and multi user
|
|
||||||
\c regression - - :master_port
|
|
||||||
create user myuser8;
|
|
||||||
create user myuser_2;
|
|
||||||
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
create database test_db;
|
|
||||||
|
|
||||||
revoke connect,temp,temporary on database test_db from public;
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
grant CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db,test_db to myuser8,myuser_2;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser8','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
select check_database_privileges('myuser8','test_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
select check_database_privileges('myuser_2','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
select check_database_privileges('myuser_2','test_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
revoke CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db,test_db from myuser8 ;
|
|
||||||
|
|
||||||
--below test should succeed and should not throw any error
|
|
||||||
revoke CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db,test_db from myuser_2;
|
|
||||||
|
|
||||||
--below test should succeed and should not throw any error
|
|
||||||
revoke CREATE,CONNECT,TEMP,TEMPORARY on database test_2pc_db,test_db from myuser8 cascade;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select check_database_privileges('myuser8','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
select check_database_privileges('myuser8','test_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
select check_database_privileges('myuser_2','test_2pc_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
select check_database_privileges('myuser_2','test_db',ARRAY['CREATE', 'CONNECT', 'TEMP', 'TEMPORARY']);
|
|
||||||
|
|
||||||
|
|
||||||
\c test_2pc_db - - :master_port
|
|
||||||
|
|
||||||
reset role;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
drop user myuser_2;
|
|
||||||
drop user myuser8;
|
|
||||||
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
drop database test_db;
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
-- rollbacks public role database privileges to original state
|
|
||||||
grant connect,temp,temporary on database test_2pc_db to public;
|
|
||||||
drop database test_2pc_db;
|
|
||||||
set citus.enable_create_database_propagation to off;
|
|
||||||
DROP SCHEMA grant_on_database_propagation_non_maindb CASCADE;
|
|
||||||
|
|
||||||
reset citus.enable_create_database_propagation;
|
|
||||||
reset search_path;
|
|
||||||
---------------------------------------------------------------------------
|
|
|
@ -1,147 +0,0 @@
|
||||||
CREATE SCHEMA grant_role2pc;
|
|
||||||
SET search_path TO grant_role2pc;
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
|
|
||||||
CREATE DATABASE grant_role2pc_db;
|
|
||||||
|
|
||||||
\c grant_role2pc_db
|
|
||||||
SHOW citus.main_db;
|
|
||||||
|
|
||||||
SET citus.superuser TO 'postgres';
|
|
||||||
CREATE USER grant_role2pc_user1;
|
|
||||||
CREATE USER grant_role2pc_user2;
|
|
||||||
CREATE USER grant_role2pc_user3;
|
|
||||||
CREATE USER grant_role2pc_user4;
|
|
||||||
CREATE USER grant_role2pc_user5;
|
|
||||||
CREATE USER grant_role2pc_user6;
|
|
||||||
CREATE USER grant_role2pc_user7;
|
|
||||||
|
|
||||||
\c grant_role2pc_db
|
|
||||||
|
|
||||||
--test with empty superuser
|
|
||||||
SET citus.superuser TO '';
|
|
||||||
grant grant_role2pc_user1 to grant_role2pc_user2;
|
|
||||||
|
|
||||||
SET citus.superuser TO 'postgres';
|
|
||||||
grant grant_role2pc_user1 to grant_role2pc_user2 with admin option granted by CURRENT_USER;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes(
|
|
||||||
$$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option
|
|
||||||
FROM pg_auth_members
|
|
||||||
WHERE member::regrole::text = 'grant_role2pc_user2'
|
|
||||||
order by member::regrole::text, roleid::regrole::text
|
|
||||||
) t
|
|
||||||
$$
|
|
||||||
);
|
|
||||||
|
|
||||||
\c grant_role2pc_db
|
|
||||||
--test grant under transactional context with multiple operations
|
|
||||||
BEGIN;
|
|
||||||
grant grant_role2pc_user1,grant_role2pc_user2 to grant_role2pc_user3 WITH ADMIN OPTION;
|
|
||||||
grant grant_role2pc_user1 to grant_role2pc_user4 granted by grant_role2pc_user3 ;
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
grant grant_role2pc_user1 to grant_role2pc_user5 WITH ADMIN OPTION granted by grant_role2pc_user3;
|
|
||||||
grant grant_role2pc_user1 to grant_role2pc_user6;
|
|
||||||
ROLLBACK;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
grant grant_role2pc_user1 to grant_role2pc_user7;
|
|
||||||
SELECT 1/0;
|
|
||||||
commit;
|
|
||||||
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option
|
|
||||||
FROM pg_auth_members
|
|
||||||
WHERE member::regrole::text in
|
|
||||||
('grant_role2pc_user3','grant_role2pc_user4','grant_role2pc_user5','grant_role2pc_user6','grant_role2pc_user7')
|
|
||||||
order by member::regrole::text, roleid::regrole::text
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
|
|
||||||
\c grant_role2pc_db
|
|
||||||
|
|
||||||
grant grant_role2pc_user1,grant_role2pc_user2 to grant_role2pc_user5,grant_role2pc_user6,grant_role2pc_user7 granted by grant_role2pc_user3;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option
|
|
||||||
FROM pg_auth_members
|
|
||||||
WHERE member::regrole::text in
|
|
||||||
('grant_role2pc_user5','grant_role2pc_user6','grant_role2pc_user7')
|
|
||||||
order by member::regrole::text, roleid::regrole::text
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
\c grant_role2pc_db
|
|
||||||
revoke admin option for grant_role2pc_user1 from grant_role2pc_user5 granted by grant_role2pc_user3;
|
|
||||||
|
|
||||||
--test revoke under transactional context with multiple operations
|
|
||||||
BEGIN;
|
|
||||||
revoke grant_role2pc_user1 from grant_role2pc_user5 granted by grant_role2pc_user3 ;
|
|
||||||
revoke grant_role2pc_user1 from grant_role2pc_user4 granted by grant_role2pc_user3;
|
|
||||||
COMMIT;
|
|
||||||
\c grant_role2pc_db - - :worker_1_port
|
|
||||||
BEGIN;
|
|
||||||
revoke grant_role2pc_user1 from grant_role2pc_user6,grant_role2pc_user7 granted by grant_role2pc_user3;
|
|
||||||
revoke grant_role2pc_user1 from grant_role2pc_user3 cascade;
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option
|
|
||||||
FROM pg_auth_members
|
|
||||||
WHERE member::regrole::text in
|
|
||||||
('grant_role2pc_user2','grant_role2pc_user3','grant_role2pc_user4','grant_role2pc_user5','grant_role2pc_user6','grant_role2pc_user7')
|
|
||||||
order by member::regrole::text, roleid::regrole::text
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
\c grant_role2pc_db - - :worker_1_port
|
|
||||||
BEGIN;
|
|
||||||
grant grant_role2pc_user1 to grant_role2pc_user5 WITH ADMIN OPTION;
|
|
||||||
grant grant_role2pc_user1 to grant_role2pc_user6;
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option
|
|
||||||
FROM pg_auth_members
|
|
||||||
WHERE member::regrole::text in
|
|
||||||
('grant_role2pc_user5','grant_role2pc_user6')
|
|
||||||
order by member::regrole::text, roleid::regrole::text
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
revoke grant_role2pc_user1 from grant_role2pc_user5,grant_role2pc_user6;
|
|
||||||
|
|
||||||
--clean resources
|
|
||||||
DROP SCHEMA grant_role2pc;
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
DROP DATABASE grant_role2pc_db;
|
|
||||||
drop user grant_role2pc_user2,grant_role2pc_user3,grant_role2pc_user4,grant_role2pc_user5,grant_role2pc_user6,grant_role2pc_user7;
|
|
||||||
drop user grant_role2pc_user1;
|
|
||||||
reset citus.enable_create_database_propagation;
|
|
|
@ -1,188 +0,0 @@
|
||||||
CREATE SCHEMA metadata_sync_2pc_schema;
|
|
||||||
SET search_path TO metadata_sync_2pc_schema;
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
CREATE DATABASE metadata_sync_2pc_db;
|
|
||||||
|
|
||||||
revoke connect,temp,temporary on database metadata_sync_2pc_db from public;
|
|
||||||
|
|
||||||
\c metadata_sync_2pc_db
|
|
||||||
SHOW citus.main_db;
|
|
||||||
|
|
||||||
CREATE USER "grant_role2pc'_user1";
|
|
||||||
CREATE USER "grant_role2pc'_user2";
|
|
||||||
CREATE USER "grant_role2pc'_user3";
|
|
||||||
CREATE USER grant_role2pc_user4;
|
|
||||||
CREATE USER grant_role2pc_user5;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
select 1 from citus_remove_node('localhost', :worker_2_port);
|
|
||||||
|
|
||||||
\c metadata_sync_2pc_db
|
|
||||||
grant "grant_role2pc'_user1","grant_role2pc'_user2" to "grant_role2pc'_user3" WITH ADMIN OPTION;
|
|
||||||
-- This section was originally testing a scenario where a user with the 'admin option' grants the same role to another user, also with the 'admin option'.
|
|
||||||
-- However, we encountered inconsistent errors because the 'admin option' grant is executed after the grant below.
|
|
||||||
-- Once we establish the correct order of granting, we will reintroduce the 'granted by' clause.
|
|
||||||
-- For now, we are commenting out the grant below that includes 'granted by', and instead, we are adding a grant without the 'granted by' clause.
|
|
||||||
-- grant "grant_role2pc'_user1","grant_role2pc'_user2" to grant_role2pc_user4,grant_role2pc_user5 granted by "grant_role2pc'_user3";
|
|
||||||
grant "grant_role2pc'_user1","grant_role2pc'_user2" to grant_role2pc_user4,grant_role2pc_user5;
|
|
||||||
|
|
||||||
--test for grant on database
|
|
||||||
\c metadata_sync_2pc_db - - :master_port
|
|
||||||
grant create on database metadata_sync_2pc_db to "grant_role2pc'_user1";
|
|
||||||
grant connect on database metadata_sync_2pc_db to "grant_role2pc'_user2";
|
|
||||||
grant ALL on database metadata_sync_2pc_db to "grant_role2pc'_user3";
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
select check_database_privileges('grant_role2pc''_user1','metadata_sync_2pc_db',ARRAY['CREATE']);
|
|
||||||
select check_database_privileges('grant_role2pc''_user2','metadata_sync_2pc_db',ARRAY['CONNECT']);
|
|
||||||
select check_database_privileges('grant_role2pc''_user3','metadata_sync_2pc_db',ARRAY['CREATE','CONNECT','TEMP','TEMPORARY']);
|
|
||||||
|
|
||||||
-- test for security label on role
|
|
||||||
\c metadata_sync_2pc_db - - :master_port
|
|
||||||
SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE grant_role2pc_user4 IS 'citus_unclassified';
|
|
||||||
SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE "grant_role2pc'_user1" IS 'citus_classified';
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels('grant_role2pc_user4') ORDER BY node_type;
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels($$"grant_role2pc''_user1"$$) ORDER BY node_type;
|
|
||||||
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
select 1 from citus_add_node('localhost', :worker_2_port);
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option
|
|
||||||
FROM pg_auth_members
|
|
||||||
WHERE member::regrole::text in
|
|
||||||
('"grant_role2pc''_user2"','"grant_role2pc''_user3"','grant_role2pc_user4','grant_role2pc_user5')
|
|
||||||
order by member::regrole::text
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
select check_database_privileges('grant_role2pc''_user1','metadata_sync_2pc_db',ARRAY['CREATE']);
|
|
||||||
select check_database_privileges('grant_role2pc''_user2','metadata_sync_2pc_db',ARRAY['CONNECT']);
|
|
||||||
select check_database_privileges('grant_role2pc''_user3','metadata_sync_2pc_db',ARRAY['CREATE','CONNECT','TEMP','TEMPORARY']);
|
|
||||||
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels('grant_role2pc_user4') ORDER BY node_type;
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels($$"grant_role2pc''_user1"$$) ORDER BY node_type;
|
|
||||||
|
|
||||||
\c metadata_sync_2pc_db
|
|
||||||
revoke "grant_role2pc'_user1","grant_role2pc'_user2" from grant_role2pc_user4,grant_role2pc_user5 ;
|
|
||||||
|
|
||||||
revoke admin option for "grant_role2pc'_user1","grant_role2pc'_user2" from "grant_role2pc'_user3";
|
|
||||||
|
|
||||||
revoke "grant_role2pc'_user1","grant_role2pc'_user2" from "grant_role2pc'_user3";
|
|
||||||
revoke ALL on database metadata_sync_2pc_db from "grant_role2pc'_user3";
|
|
||||||
revoke CONNECT on database metadata_sync_2pc_db from "grant_role2pc'_user2";
|
|
||||||
revoke CREATE on database metadata_sync_2pc_db from "grant_role2pc'_user1";
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
|
|
||||||
drop user "grant_role2pc'_user1","grant_role2pc'_user2","grant_role2pc'_user3",grant_role2pc_user4,grant_role2pc_user5;
|
|
||||||
--test for user operations
|
|
||||||
|
|
||||||
--test for create user
|
|
||||||
\c regression - - :master_port
|
|
||||||
select 1 from citus_remove_node('localhost', :worker_2_port);
|
|
||||||
|
|
||||||
\c metadata_sync_2pc_db - - :master_port
|
|
||||||
CREATE ROLE test_role1 WITH LOGIN PASSWORD 'password1';
|
|
||||||
|
|
||||||
\c metadata_sync_2pc_db - - :worker_1_port
|
|
||||||
CREATE USER "test_role2-needs\!escape"
|
|
||||||
WITH
|
|
||||||
SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION
|
|
||||||
LIMIT 10 VALID UNTIL '2023-01-01' IN ROLE test_role1;
|
|
||||||
|
|
||||||
create role test_role3;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select 1 from citus_add_node('localhost', :worker_2_port);
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb,
|
|
||||||
rolcanlogin, rolreplication, rolbypassrls, rolconnlimit,
|
|
||||||
(rolpassword != '') as pass_not_empty, DATE(rolvaliduntil)
|
|
||||||
FROM pg_authid
|
|
||||||
WHERE rolname in ('test_role1', 'test_role2-needs\!escape','test_role3')
|
|
||||||
ORDER BY rolname
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
--test for alter user
|
|
||||||
select 1 from citus_remove_node('localhost', :worker_2_port);
|
|
||||||
\c metadata_sync_2pc_db - - :master_port
|
|
||||||
-- Test ALTER ROLE with various options
|
|
||||||
ALTER ROLE test_role1 WITH PASSWORD 'new_password1';
|
|
||||||
|
|
||||||
\c metadata_sync_2pc_db - - :worker_1_port
|
|
||||||
ALTER USER "test_role2-needs\!escape"
|
|
||||||
WITH
|
|
||||||
NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION
|
|
||||||
LIMIT 5 VALID UNTIL '2024-01-01';
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select 1 from citus_add_node('localhost', :worker_2_port);
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb,
|
|
||||||
rolcanlogin, rolreplication, rolbypassrls, rolconnlimit,
|
|
||||||
(rolpassword != '') as pass_not_empty, DATE(rolvaliduntil)
|
|
||||||
FROM pg_authid
|
|
||||||
WHERE rolname in ('test_role1', 'test_role2-needs\!escape','test_role3')
|
|
||||||
ORDER BY rolname
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
--test for drop user
|
|
||||||
select 1 from citus_remove_node('localhost', :worker_2_port);
|
|
||||||
|
|
||||||
\c metadata_sync_2pc_db - - :worker_1_port
|
|
||||||
DROP ROLE test_role1, "test_role2-needs\!escape";
|
|
||||||
|
|
||||||
\c metadata_sync_2pc_db - - :master_port
|
|
||||||
DROP ROLE test_role3;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select 1 from citus_add_node('localhost', :worker_2_port);
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb,
|
|
||||||
rolcanlogin, rolreplication, rolbypassrls, rolconnlimit,
|
|
||||||
(rolpassword != '') as pass_not_empty, DATE(rolvaliduntil)
|
|
||||||
FROM pg_authid
|
|
||||||
WHERE rolname in ('test_role1', 'test_role2-needs\!escape','test_role3')
|
|
||||||
ORDER BY rolname
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
-- Clean up: drop the database on worker node 2
|
|
||||||
\c regression - - :worker_2_port
|
|
||||||
DROP ROLE if exists test_role1, "test_role2-needs\!escape", test_role3;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb,
|
|
||||||
rolcanlogin, rolreplication, rolbypassrls, rolconnlimit,
|
|
||||||
(rolpassword != '') as pass_not_empty, DATE(rolvaliduntil)
|
|
||||||
FROM pg_authid
|
|
||||||
WHERE rolname in ('test_role1', 'test_role2-needs\!escape','test_role3')
|
|
||||||
ORDER BY rolname
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
drop database metadata_sync_2pc_db;
|
|
||||||
drop schema metadata_sync_2pc_schema;
|
|
||||||
reset citus.enable_create_database_propagation;
|
|
||||||
reset search_path;
|
|
|
@ -1,182 +0,0 @@
|
||||||
CREATE SCHEMA other_databases;
|
|
||||||
SET search_path TO other_databases;
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 10231023;
|
|
||||||
|
|
||||||
CREATE DATABASE other_db1;
|
|
||||||
|
|
||||||
\c other_db1
|
|
||||||
SHOW citus.main_db;
|
|
||||||
|
|
||||||
-- check that empty citus.superuser gives error
|
|
||||||
SET citus.superuser TO '';
|
|
||||||
CREATE USER empty_superuser;
|
|
||||||
SET citus.superuser TO 'postgres';
|
|
||||||
|
|
||||||
CREATE USER other_db_user1;
|
|
||||||
CREATE USER other_db_user2;
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
CREATE USER other_db_user3;
|
|
||||||
CREATE USER other_db_user4;
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
CREATE USER other_db_user5;
|
|
||||||
CREATE USER other_db_user6;
|
|
||||||
ROLLBACK;
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
CREATE USER other_db_user7;
|
|
||||||
SELECT 1/0;
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
CREATE USER other_db_user8;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
SELECT usename FROM pg_user WHERE usename LIKE 'other\_db\_user%' ORDER BY 1;
|
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT usename FROM pg_user WHERE usename LIKE 'other\_db\_user%' ORDER BY 1;
|
|
||||||
|
|
||||||
\c - - - :master_port
|
|
||||||
-- some user creation commands will fail but let's make sure we try to drop them just in case
|
|
||||||
DROP USER IF EXISTS other_db_user1, other_db_user2, other_db_user3, other_db_user4, other_db_user5, other_db_user6, other_db_user7, other_db_user8;
|
|
||||||
|
|
||||||
-- Make sure non-superuser roles cannot use internal GUCs
|
|
||||||
-- but they can still create a role
|
|
||||||
CREATE USER nonsuperuser CREATEROLE;
|
|
||||||
GRANT ALL ON SCHEMA citus_internal TO nonsuperuser;
|
|
||||||
SET ROLE nonsuperuser;
|
|
||||||
SELECT citus_internal.execute_command_on_remote_nodes_as_user($$SELECT 'dangerous query'$$, 'postgres');
|
|
||||||
|
|
||||||
\c other_db1
|
|
||||||
SET citus.local_hostname TO '127.0.0.1';
|
|
||||||
SET ROLE nonsuperuser;
|
|
||||||
|
|
||||||
-- Make sure that we don't try to access pg_dist_node.
|
|
||||||
-- Otherwise, we would get the following error:
|
|
||||||
-- ERROR: cache lookup failed for pg_dist_node, called too early?
|
|
||||||
CREATE USER other_db_user9;
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
RESET citus.local_hostname;
|
|
||||||
RESET ROLE;
|
|
||||||
\c regression
|
|
||||||
SELECT usename FROM pg_user WHERE usename LIKE 'other\_db\_user%' ORDER BY 1;
|
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT usename FROM pg_user WHERE usename LIKE 'other\_db\_user%' ORDER BY 1;
|
|
||||||
|
|
||||||
\c - - - :master_port
|
|
||||||
REVOKE ALL ON SCHEMA citus_internal FROM nonsuperuser;
|
|
||||||
DROP USER other_db_user9, nonsuperuser;
|
|
||||||
|
|
||||||
-- test from a worker
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
|
|
||||||
CREATE DATABASE worker_other_db;
|
|
||||||
|
|
||||||
\c worker_other_db
|
|
||||||
|
|
||||||
CREATE USER worker_user1;
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
CREATE USER worker_user2;
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
CREATE USER worker_user3;
|
|
||||||
ROLLBACK;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
SELECT usename FROM pg_user WHERE usename LIKE 'worker\_user%' ORDER BY 1;
|
|
||||||
|
|
||||||
\c - - - :master_port
|
|
||||||
SELECT usename FROM pg_user WHERE usename LIKE 'worker\_user%' ORDER BY 1;
|
|
||||||
|
|
||||||
-- some user creation commands will fail but let's make sure we try to drop them just in case
|
|
||||||
DROP USER IF EXISTS worker_user1, worker_user2, worker_user3;
|
|
||||||
|
|
||||||
-- test creating and dropping a database from a Citus non-main database
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$ALTER SYSTEM SET citus.enable_create_database_propagation TO true$$);
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$SELECT pg_reload_conf()$$);
|
|
||||||
SELECT pg_sleep(0.1);
|
|
||||||
\c other_db1
|
|
||||||
CREATE DATABASE other_db3;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
SELECT * FROM public.check_database_on_all_nodes('other_db3') ORDER BY node_type;
|
|
||||||
|
|
||||||
\c other_db1
|
|
||||||
DROP DATABASE other_db3;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
SELECT * FROM public.check_database_on_all_nodes('other_db3') ORDER BY node_type;
|
|
||||||
|
|
||||||
\c worker_other_db - - :worker_1_port
|
|
||||||
CREATE DATABASE other_db4;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
SELECT * FROM public.check_database_on_all_nodes('other_db4') ORDER BY node_type;
|
|
||||||
|
|
||||||
\c worker_other_db
|
|
||||||
DROP DATABASE other_db4;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
SELECT * FROM public.check_database_on_all_nodes('other_db4') ORDER BY node_type;
|
|
||||||
|
|
||||||
DROP DATABASE worker_other_db;
|
|
||||||
|
|
||||||
CREATE DATABASE other_db5;
|
|
||||||
|
|
||||||
-- disable create database propagation for the next test
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$ALTER SYSTEM SET citus.enable_create_database_propagation TO false$$);
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$SELECT pg_reload_conf()$$);
|
|
||||||
SELECT pg_sleep(0.1);
|
|
||||||
|
|
||||||
\c other_db5 - - :worker_2_port
|
|
||||||
|
|
||||||
-- locally create a database
|
|
||||||
CREATE DATABASE local_db;
|
|
||||||
|
|
||||||
\c regression - - -
|
|
||||||
|
|
||||||
-- re-enable create database propagation
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$ALTER SYSTEM SET citus.enable_create_database_propagation TO true$$);
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$SELECT pg_reload_conf()$$);
|
|
||||||
SELECT pg_sleep(0.1);
|
|
||||||
|
|
||||||
\c other_db5 - - :master_port
|
|
||||||
|
|
||||||
-- Test a scenario where create database fails because the database
|
|
||||||
-- already exists on another node and we don't crash etc.
|
|
||||||
CREATE DATABASE local_db;
|
|
||||||
|
|
||||||
\c regression - - -
|
|
||||||
|
|
||||||
SELECT * FROM public.check_database_on_all_nodes('local_db') ORDER BY node_type, result;
|
|
||||||
|
|
||||||
\c - - - :worker_2_port
|
|
||||||
|
|
||||||
-- locally drop the database for cleanup purposes
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$ALTER SYSTEM SET citus.enable_create_database_propagation TO false$$);
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$SELECT pg_reload_conf()$$);
|
|
||||||
SELECT pg_sleep(0.1);
|
|
||||||
|
|
||||||
DROP DATABASE local_db;
|
|
||||||
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$ALTER SYSTEM SET citus.enable_create_database_propagation TO true$$);
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$SELECT pg_reload_conf()$$);
|
|
||||||
SELECT pg_sleep(0.1);
|
|
||||||
|
|
||||||
\c - - - :master_port
|
|
||||||
|
|
||||||
DROP DATABASE other_db5;
|
|
||||||
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$ALTER SYSTEM SET citus.enable_create_database_propagation TO false$$);
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$SELECT pg_reload_conf()$$);
|
|
||||||
SELECT pg_sleep(0.1);
|
|
||||||
|
|
||||||
DROP SCHEMA other_databases;
|
|
||||||
DROP DATABASE other_db1;
|
|
|
@ -1,106 +0,0 @@
|
||||||
-- Create a new database
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
CREATE DATABASE role_operations_test_db;
|
|
||||||
SET citus.superuser TO 'postgres';
|
|
||||||
-- Connect to the new database
|
|
||||||
\c role_operations_test_db
|
|
||||||
-- Test CREATE ROLE with various options
|
|
||||||
CREATE ROLE test_role1 WITH LOGIN PASSWORD 'password1';
|
|
||||||
|
|
||||||
\c role_operations_test_db - - :worker_1_port
|
|
||||||
CREATE USER "test_role2-needs\!escape"
|
|
||||||
WITH
|
|
||||||
SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION
|
|
||||||
LIMIT 10 VALID UNTIL '2023-01-01' IN ROLE test_role1;
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb,
|
|
||||||
rolcanlogin, rolreplication, rolbypassrls, rolconnlimit,
|
|
||||||
(rolpassword != '') as pass_not_empty, DATE(rolvaliduntil)
|
|
||||||
FROM pg_authid
|
|
||||||
WHERE rolname in ('test_role1', 'test_role2-needs\!escape')
|
|
||||||
ORDER BY rolname
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT r.rolname
|
|
||||||
FROM pg_dist_object d
|
|
||||||
JOIN pg_roles r ON d.objid = r.oid
|
|
||||||
WHERE r.rolname IN ('test_role1', 'test_role2-needs\!escape')
|
|
||||||
order by r.rolname
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
\c role_operations_test_db - - :master_port
|
|
||||||
-- Test ALTER ROLE with various options
|
|
||||||
ALTER ROLE test_role1 WITH PASSWORD 'new_password1';
|
|
||||||
|
|
||||||
\c role_operations_test_db - - :worker_1_port
|
|
||||||
ALTER USER "test_role2-needs\!escape"
|
|
||||||
WITH
|
|
||||||
NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION
|
|
||||||
LIMIT 5 VALID UNTIL '2024-01-01';
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb,
|
|
||||||
rolcanlogin, rolreplication, rolbypassrls, rolconnlimit,
|
|
||||||
(rolpassword != '') as pass_not_empty, DATE(rolvaliduntil)
|
|
||||||
FROM pg_authid
|
|
||||||
WHERE rolname in ('test_role1', 'test_role2-needs\!escape')
|
|
||||||
ORDER BY rolname
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
\c role_operations_test_db - - :master_port
|
|
||||||
-- Test DROP ROLE
|
|
||||||
DROP ROLE no_such_role; -- fails nicely
|
|
||||||
DROP ROLE IF EXISTS no_such_role; -- doesn't fail
|
|
||||||
|
|
||||||
CREATE ROLE new_role;
|
|
||||||
DROP ROLE IF EXISTS no_such_role, new_role; -- doesn't fail
|
|
||||||
DROP ROLE IF EXISTS test_role1, "test_role2-needs\!escape";
|
|
||||||
|
|
||||||
\c regression - - :master_port
|
|
||||||
--verify that roles and dist_object are dropped
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb,
|
|
||||||
rolcanlogin, rolreplication, rolbypassrls, rolconnlimit,
|
|
||||||
(rolpassword != '') as pass_not_empty, DATE(rolvaliduntil)
|
|
||||||
FROM pg_authid
|
|
||||||
WHERE rolname in ('test_role1', 'test_role2-needs\!escape','new_role','no_such_role')
|
|
||||||
ORDER BY rolname
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
|
||||||
FROM (
|
|
||||||
SELECT r.rolname
|
|
||||||
FROM pg_roles r
|
|
||||||
WHERE r.rolname IN ('test_role1', 'test_role2-needs\!escape','new_role','no_such_role')
|
|
||||||
order by r.rolname
|
|
||||||
) t
|
|
||||||
$$);
|
|
||||||
|
|
||||||
SELECT result FROM run_command_on_all_nodes($$
|
|
||||||
SELECT count(*) leaked_pg_dist_object_records_for_roles
|
|
||||||
FROM pg_dist_object LEFT JOIN pg_authid ON (objid = oid)
|
|
||||||
WHERE classid = 1260 AND oid IS NULL
|
|
||||||
$$);
|
|
||||||
|
|
||||||
-- Clean up: drop the database
|
|
||||||
set citus.enable_create_database_propagation to on;
|
|
||||||
DROP DATABASE role_operations_test_db;
|
|
||||||
reset citus.enable_create_database_propagation;
|
|
|
@ -1,71 +0,0 @@
|
||||||
-- SECLABEL
|
|
||||||
--
|
|
||||||
-- Test suite for running SECURITY LABEL ON ROLE statements from non-main databases
|
|
||||||
|
|
||||||
SET citus.enable_create_database_propagation to ON;
|
|
||||||
|
|
||||||
CREATE DATABASE database1;
|
|
||||||
CREATE DATABASE database2;
|
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SET citus.enable_create_database_propagation to ON;
|
|
||||||
CREATE DATABASE database_w1;
|
|
||||||
|
|
||||||
|
|
||||||
\c - - - :master_port
|
|
||||||
CREATE ROLE user1;
|
|
||||||
\c database1
|
|
||||||
SHOW citus.main_db;
|
|
||||||
SHOW citus.superuser;
|
|
||||||
|
|
||||||
CREATE ROLE "user 2";
|
|
||||||
|
|
||||||
-- Set a SECURITY LABEL on a role from a non-main database
|
|
||||||
SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE user1 IS 'citus_classified';
|
|
||||||
SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE "user 2" IS 'citus_unclassified';
|
|
||||||
|
|
||||||
-- Check the result
|
|
||||||
\c regression
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels('user1') ORDER BY node_type;
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels('"user 2"') ORDER BY node_type;
|
|
||||||
|
|
||||||
\c database1
|
|
||||||
-- Set a SECURITY LABEL on database, it should not be propagated
|
|
||||||
SECURITY LABEL FOR "citus '!tests_label_provider" ON DATABASE database1 IS 'citus_classified';
|
|
||||||
|
|
||||||
-- Set a SECURITY LABEL on a table, it should not be propagated
|
|
||||||
CREATE TABLE a (i int);
|
|
||||||
SECURITY LABEL ON TABLE a IS 'citus_classified';
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels('database1') ORDER BY node_type;
|
|
||||||
|
|
||||||
-- Check that only the SECURITY LABEL for ROLES is propagated to the non-main databases on other nodes
|
|
||||||
\c database_w1 - - :worker_1_port
|
|
||||||
SELECT provider, objtype, label, objname FROM pg_seclabels ORDER BY objname;
|
|
||||||
|
|
||||||
|
|
||||||
-- Check the result after a transaction
|
|
||||||
BEGIN;
|
|
||||||
SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE user1 IS 'citus_unclassified';
|
|
||||||
SECURITY LABEL FOR "citus '!tests_label_provider" ON DATABASE database_w1 IS 'citus_classified';
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
\c regression
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels('database_w1') ORDER BY node_type;
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels('user1') ORDER BY node_type;
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE "user 2" IS 'citus_classified';
|
|
||||||
ROLLBACK;
|
|
||||||
|
|
||||||
SELECT node_type, result FROM get_citus_tests_label_provider_labels('"user 2"') ORDER BY node_type;
|
|
||||||
|
|
||||||
-- clean up
|
|
||||||
SET citus.enable_create_database_propagation to ON;
|
|
||||||
DROP DATABASE database1;
|
|
||||||
DROP DATABASE database2;
|
|
||||||
DROP DATABASE database_w1;
|
|
||||||
DROP ROLE user1;
|
|
||||||
DROP ROLE "user 2";
|
|
||||||
RESET citus.enable_create_database_propagation;
|
|
Loading…
Reference in New Issue