Fixes review comments

pull/7319/head
gurkanindibay 2023-12-25 17:03:59 +03:00
parent b5b6ecdb59
commit e01d85bf4d
6 changed files with 58 additions and 60 deletions

View File

@ -42,44 +42,44 @@ static void EnsureDependenciesCanBeDistributed(const ObjectAddress *relationAddr
static void ErrorIfCircularDependencyExists(const ObjectAddress *objectAddress);
static int ObjectAddressComparator(const void *a, const void *b);
static void EnsureDependenciesExistOnAllNodes(const ObjectAddress *target);
static void EnsureRequiredObjectExistOnAllNodes(const ObjectAddress *target,
RequiredObjectSet requiredObjectSet);
static void EnsureRequiredObjectSetExistOnAllNodes(const ObjectAddress *target,
RequiredObjectSet requiredObjectSet);
static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency);
static bool ShouldPropagateObject(const ObjectAddress *address);
static char * DropTableIfExistsCommand(Oid relationId);
/*
* EnsureObjectAndDependenciesExistOnAllNodes is a wrapper around
* EnsureRequiredObjectExistOnAllNodes to ensure the "object itself" (together
* EnsureRequiredObjectSetExistOnAllNodes to ensure the "object itself" (together
* with its dependencies) is available on all nodes.
*
* See EnsureRequiredObjectExistOnAllNodes to learn more about how this
* See EnsureRequiredObjectSetExistOnAllNodes to learn more about how this
* function deals with an object created within the same transaction.
*/
void
EnsureObjectAndDependenciesExistOnAllNodes(const ObjectAddress *target)
{
EnsureRequiredObjectExistOnAllNodes(target, REQUIRE_OBJECT_AND_DEPENDENCIES);
EnsureRequiredObjectSetExistOnAllNodes(target, REQUIRE_OBJECT_AND_DEPENDENCIES);
}
/*
* EnsureDependenciesExistOnAllNodes is a wrapper around
* EnsureRequiredObjectExistOnAllNodes to ensure "all dependencies" of given
* EnsureRequiredObjectSetExistOnAllNodes to ensure "all dependencies" of given
* object --but not the object itself-- are available on all nodes.
*
* See EnsureRequiredObjectExistOnAllNodes to learn more about how this
* See EnsureRequiredObjectSetExistOnAllNodes to learn more about how this
* function deals with an object created within the same transaction.
*/
static void
EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
{
EnsureRequiredObjectExistOnAllNodes(target, REQUIRE_ONLY_DEPENDENCIES);
EnsureRequiredObjectSetExistOnAllNodes(target, REQUIRE_ONLY_DEPENDENCIES);
}
/*
* EnsureRequiredObjectExistOnAllNodes finds all the dependencies that we support and makes
* EnsureRequiredObjectSetExistOnAllNodes finds all the dependencies that we support and makes
* sure these are available on all nodes if required object set is REQUIRE_ONLY_DEPENDENCIES.
* Otherwise, i.e., if required object set is REQUIRE_OBJECT_AND_DEPENDENCIES, then this
* function creates the object itself on all nodes too. This function ensures that each
@ -100,8 +100,8 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
* postgres native CREATE IF NOT EXISTS, or citus helper functions.
*/
static void
EnsureRequiredObjectExistOnAllNodes(const ObjectAddress *target,
RequiredObjectSet requiredObjectSet)
EnsureRequiredObjectSetExistOnAllNodes(const ObjectAddress *target,
RequiredObjectSet requiredObjectSet)
{
Assert(requiredObjectSet == REQUIRE_ONLY_DEPENDENCIES ||
requiredObjectSet == REQUIRE_OBJECT_AND_DEPENDENCIES);

View File

@ -281,7 +281,7 @@ static DistributeObjectOps Any_ReassignOwned = {
.qualify = NULL,
.preprocess = NULL,
.postprocess = PostprocessReassignOwnedStmt,
.operationType = DIST_OPS_DROP,
.operationType = DIST_OPS_ALTER,
.address = NULL,
.markDistributed = false,
};

View File

@ -95,14 +95,14 @@ PreprocessDropOwnedStmt(Node *node, const char *queryString,
/*
* PostprocessReassignOwnedStmt Post-processes a REASSIGN OWNED statement.
* PostprocessReassignOwnedStmt takes a Node pointer representing a REASSIGN
* OWNED statement and performs any necessary post-processing after the statement
* has been executed locally.
*
* This function takes a Node pointer representing a REASSIGN OWNED statement,
* and performs any necessary post-processing after the statement has been executed.
* In this method, we propagate all the roles that are being reassigned.
* Therefore, we don't filter the roles based on whether they are distributed or not.
* If roles are not distributed and those roles are not present in the nodes
* where the statement is being propagated, then the statement will fail.
* We filter out local roles in OWNED BY clause before deparsing the command,
* meaning that we skip reassigning what is owned by local roles. However,
* if the role specified in TO clause is local, we automatically distribute
* it before deparsing the command.
*/
List *
PostprocessReassignOwnedStmt(Node *node, const char *queryString)
@ -130,6 +130,10 @@ PostprocessReassignOwnedStmt(Node *node, const char *queryString)
ObjectAddress *newRoleAddress = GetNewRoleAddress(stmt);
/*
* We temporarily enable create / alter role propagation to properly
* propagate the role specified in TO clause.
*/
int saveNestLevel = NewGUCNestLevel();
set_config_option("citus.enable_create_role_propagation", "on",
(superuser() ? PGC_SUSET : PGC_USERSET), PGC_S_SESSION,
@ -156,8 +160,7 @@ PostprocessReassignOwnedStmt(Node *node, const char *queryString)
/*
* GetNewRoleAddress returns the ObjectAddress of the new role.
* in the ReassignOwnedStmt.
* GetNewRoleAddress returns the ObjectAddress of the new role
*/
static ObjectAddress *
GetNewRoleAddress(ReassignOwnedStmt *stmt)

View File

@ -92,7 +92,7 @@ AppendReassignOwnedStmt(StringInfo buf, ReassignOwnedStmt *stmt)
AppendRoleList(buf, stmt->roles);
char const *newRoleName = RoleSpecString(stmt->newrole, true);
appendStringInfo(buf, " TO %s", quote_identifier(newRoleName));
appendStringInfo(buf, " TO %s", newRoleName);
}

View File

@ -1,15 +1,20 @@
CREATE ROLE distributed_source_role1;
create ROLE "distributed_source_role-\!";
CREATE ROLE distributed_target_role1;
CREATE ROLE "distributed_target_role1-\!";
set citus.enable_create_role_propagation to off;
create ROLE local_target_role1;
NOTICE: not propagating CREATE ROLE/USER commands to other nodes
HINT: Connect to other nodes directly to manually create all necessary users and roles.
alter role local_target_role1 SET work_mem = '64MB';
\c - - - :worker_1_port
set citus.enable_create_role_propagation to off;
CREATE ROLE local_target_role1;
NOTICE: not propagating CREATE ROLE/USER commands to other nodes
HINT: Connect to other nodes directly to manually create all necessary users and roles.
\c - - - :master_port
set citus.enable_create_role_propagation to off;
create role local_source_role1;
NOTICE: not propagating CREATE ROLE/USER commands to other nodes
HINT: Connect to other nodes directly to manually create all necessary users and roles.
reset citus.enable_create_role_propagation;
GRANT CREATE ON SCHEMA public TO distributed_source_role1,"distributed_source_role-\!";
SET ROLE distributed_source_role1;
@ -54,12 +59,12 @@ SELECT result from run_command_on_all_nodes(
--tests for reassing owned by with multiple distributed roles and a local role to a distributed role
--local role should be ignored
set citus.log_remote_commands to on;
REASSIGN OWNED BY distributed_source_role1,"distributed_source_role-\!",local_source_role1 TO distributed_target_role1;
REASSIGN OWNED BY distributed_source_role1,"distributed_source_role-\!",local_source_role1 TO "distributed_target_role1-\!";
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT worker_create_or_alter_role('distributed_target_role1', 'CREATE ROLE distributed_target_role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE distributed_target_role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''')
NOTICE: issuing SELECT worker_create_or_alter_role(E'distributed_target_role1-\\!', E'CREATE ROLE "distributed_target_role1-\\!" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', E'ALTER ROLE "distributed_target_role1-\\!" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
@ -67,7 +72,7 @@ NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT worker_create_or_alter_role('distributed_target_role1', 'CREATE ROLE distributed_target_role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE distributed_target_role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''')
NOTICE: issuing SELECT worker_create_or_alter_role(E'distributed_target_role1-\\!', E'CREATE ROLE "distributed_target_role1-\\!" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', E'ALTER ROLE "distributed_target_role1-\\!" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
@ -75,17 +80,17 @@ NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing WITH distributed_object_data(typetext, objnames, objargs, distargumentindex, colocationid, force_delegation) AS (VALUES ('role', ARRAY['distributed_target_role1']::text[], ARRAY[]::text[], -1, 0, false)) SELECT citus_internal_add_object_metadata(typetext, objnames, objargs, distargumentindex::int, colocationid::int, force_delegation::bool) FROM distributed_object_data;
NOTICE: issuing WITH distributed_object_data(typetext, objnames, objargs, distargumentindex, colocationid, force_delegation) AS (VALUES ('role', ARRAY[E'distributed_target_role1-\\!']::text[], ARRAY[]::text[], -1, 0, false)) SELECT citus_internal_add_object_metadata(typetext, objnames, objargs, distargumentindex::int, colocationid::int, force_delegation::bool) FROM distributed_object_data;
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing WITH distributed_object_data(typetext, objnames, objargs, distargumentindex, colocationid, force_delegation) AS (VALUES ('role', ARRAY['distributed_target_role1']::text[], ARRAY[]::text[], -1, 0, false)) SELECT citus_internal_add_object_metadata(typetext, objnames, objargs, distargumentindex::int, colocationid::int, force_delegation::bool) FROM distributed_object_data;
NOTICE: issuing WITH distributed_object_data(typetext, objnames, objargs, distargumentindex, colocationid, force_delegation) AS (VALUES ('role', ARRAY[E'distributed_target_role1-\\!']::text[], ARRAY[]::text[], -1, 0, false)) SELECT citus_internal_add_object_metadata(typetext, objnames, objargs, distargumentindex::int, colocationid::int, force_delegation::bool) FROM distributed_object_data;
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REASSIGN OWNED BY distributed_source_role1, "distributed_source_role-\!", local_source_role1 TO distributed_target_role1
NOTICE: issuing REASSIGN OWNED BY distributed_source_role1, "distributed_source_role-\!" TO "distributed_target_role1-\!"
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REASSIGN OWNED BY distributed_source_role1, "distributed_source_role-\!", local_source_role1 TO distributed_target_role1
NOTICE: issuing REASSIGN OWNED BY distributed_source_role1, "distributed_source_role-\!" TO "distributed_target_role1-\!"
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SET citus.enable_ddl_propagation TO 'on'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
@ -101,7 +106,7 @@ NOTICE: issuing COMMIT PREPARED 'citus_xx_xx_xx_xx'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
reset citus.grep_remote_commands;
reset citus.log_remote_commands;
--check if the owner changed to distributed_target_role1
--check if the owner changed to "distributed_target_role1-\!"
RESET citus.log_remote_commands;
SELECT result from run_command_on_all_nodes(
$$
@ -118,11 +123,11 @@ SELECT result from run_command_on_all_nodes(
) q2
$$
) ORDER BY result;
result
result
---------------------------------------------------------------------
[{"tablename": "test_table", "schemaname": "public", "tableowner": "distributed_target_role1"}, {"tablename": "test_table2", "schemaname": "public", "tableowner": "distributed_target_role1"}]
[{"tablename": "test_table", "schemaname": "public", "tableowner": "distributed_target_role1"}, {"tablename": "test_table2", "schemaname": "public", "tableowner": "distributed_target_role1"}]
[{"tablename": "test_table", "schemaname": "public", "tableowner": "distributed_target_role1"}, {"tablename": "test_table2", "schemaname": "public", "tableowner": "distributed_target_role1"}]
[{"tablename": "test_table", "schemaname": "public", "tableowner": "distributed_target_role1-\\!"}, {"tablename": "test_table2", "schemaname": "public", "tableowner": "distributed_target_role1-\\!"}]
[{"tablename": "test_table", "schemaname": "public", "tableowner": "distributed_target_role1-\\!"}, {"tablename": "test_table2", "schemaname": "public", "tableowner": "distributed_target_role1-\\!"}]
[{"tablename": "test_table", "schemaname": "public", "tableowner": "distributed_target_role1-\\!"}, {"tablename": "test_table2", "schemaname": "public", "tableowner": "distributed_target_role1-\\!"}]
(3 rows)
--tests for reassing owned by with multiple distributed roles and a local role to a local role
@ -155,8 +160,6 @@ NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT worker_create_or_alter_role('local_target_role1', 'CREATE ROLE local_target_role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE local_target_role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT alter_role_if_exists('local_target_role1', 'ALTER ROLE local_target_role1 SET work_mem = 65536')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
@ -165,8 +168,6 @@ NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT worker_create_or_alter_role('local_target_role1', 'CREATE ROLE local_target_role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE local_target_role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT alter_role_if_exists('local_target_role1', 'ALTER ROLE local_target_role1 SET work_mem = 65536')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
@ -181,9 +182,9 @@ NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REASSIGN OWNED BY distributed_source_role1, "distributed_source_role-\!", local_source_role1 TO local_target_role1
NOTICE: issuing REASSIGN OWNED BY distributed_source_role1, "distributed_source_role-\!" TO local_target_role1
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REASSIGN OWNED BY distributed_source_role1, "distributed_source_role-\!", local_source_role1 TO local_target_role1
NOTICE: issuing REASSIGN OWNED BY distributed_source_role1, "distributed_source_role-\!" TO local_target_role1
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SET citus.enable_ddl_propagation TO 'on'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
@ -245,7 +246,7 @@ SELECT result from run_command_on_all_nodes(
(3 rows)
--clear resources
DROP OWNED BY distributed_source_role1, "distributed_source_role-\!",distributed_target_role1,local_target_role1;
DROP OWNED BY distributed_source_role1, "distributed_source_role-\!","distributed_target_role1-\!",local_target_role1;
SELECT result from run_command_on_all_nodes(
$$
SELECT jsonb_agg(to_jsonb(q2.*)) FROM (
@ -267,10 +268,5 @@ WHERE
(3 rows)
SET citus.log_remote_commands = true;
set citus.grep_remote_commands = '%DROP ROLE%';
drop role distributed_source_role1, "distributed_source_role-\!",distributed_target_role1,local_target_role1,local_source_role1;
NOTICE: issuing DROP ROLE distributed_source_role1, "distributed_source_role-\!", distributed_target_role1, local_target_role1, local_source_role1
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing DROP ROLE distributed_source_role1, "distributed_source_role-\!", distributed_target_role1, local_target_role1, local_source_role1
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
set client_min_messages to warning;
drop role distributed_source_role1, "distributed_source_role-\!","distributed_target_role1-\!",local_target_role1,local_source_role1;

View File

@ -1,18 +1,18 @@
CREATE ROLE distributed_source_role1;
create ROLE "distributed_source_role-\!";
CREATE ROLE distributed_target_role1;
CREATE ROLE "distributed_target_role1-\!";
set citus.enable_create_role_propagation to off;
create ROLE local_target_role1;
alter role local_target_role1 SET work_mem = '64MB';
\c - - - :worker_1_port
set citus.enable_create_role_propagation to off;
CREATE ROLE local_target_role1;
\c - - - :master_port
set citus.enable_create_role_propagation to off;
create role local_source_role1;
reset citus.enable_create_role_propagation;
@ -47,11 +47,11 @@ SELECT result from run_command_on_all_nodes(
--tests for reassing owned by with multiple distributed roles and a local role to a distributed role
--local role should be ignored
set citus.log_remote_commands to on;
REASSIGN OWNED BY distributed_source_role1,"distributed_source_role-\!",local_source_role1 TO distributed_target_role1;
REASSIGN OWNED BY distributed_source_role1,"distributed_source_role-\!",local_source_role1 TO "distributed_target_role1-\!";
reset citus.grep_remote_commands;
reset citus.log_remote_commands;
--check if the owner changed to distributed_target_role1
--check if the owner changed to "distributed_target_role1-\!"
RESET citus.log_remote_commands;
SELECT result from run_command_on_all_nodes(
@ -117,7 +117,7 @@ SELECT result from run_command_on_all_nodes(
) ORDER BY result;
--clear resources
DROP OWNED BY distributed_source_role1, "distributed_source_role-\!",distributed_target_role1,local_target_role1;
DROP OWNED BY distributed_source_role1, "distributed_source_role-\!","distributed_target_role1-\!",local_target_role1;
SELECT result from run_command_on_all_nodes(
$$
@ -135,6 +135,5 @@ WHERE
) ORDER BY result;
SET citus.log_remote_commands = true;
set citus.grep_remote_commands = '%DROP ROLE%';
drop role distributed_source_role1, "distributed_source_role-\!",distributed_target_role1,local_target_role1,local_source_role1;
set client_min_messages to warning;
drop role distributed_source_role1, "distributed_source_role-\!","distributed_target_role1-\!",local_target_role1,local_source_role1;