@ -120,6 +120,7 @@
# include "utils/rls.h"
# include "utils/snapmgr.h"
# include "utils/syscache.h"
# include "utils/usercontext.h"
static bool table_states_valid = false ;
static List * table_states_not_ready = NIL ;
@ -1252,7 +1253,9 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
WalRcvExecResult * res ;
char originname [ NAMEDATALEN ] ;
RepOriginId originid ;
UserContext ucxt ;
bool must_use_password ;
bool run_as_owner ;
/* Check the state of the table synchronization. */
StartTransactionCommand ( ) ;
@ -1374,31 +1377,6 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
*/
rel = table_open ( MyLogicalRepWorker - > relid , RowExclusiveLock ) ;
/*
* Check that our table sync worker has permission to insert into the
* target table .
*/
aclresult = pg_class_aclcheck ( RelationGetRelid ( rel ) , GetUserId ( ) ,
ACL_INSERT ) ;
if ( aclresult ! = ACLCHECK_OK )
aclcheck_error ( aclresult ,
get_relkind_objtype ( rel - > rd_rel - > relkind ) ,
RelationGetRelationName ( rel ) ) ;
/*
* COPY FROM does not honor RLS policies . That is not a problem for
* subscriptions owned by roles with BYPASSRLS privilege ( or superuser ,
* who has it implicitly ) , but other roles should not be able to
* circumvent RLS . Disallow logical replication into RLS enabled
* relations for such roles .
*/
if ( check_enable_rls ( RelationGetRelid ( rel ) , InvalidOid , false ) = = RLS_ENABLED )
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " user \" %s \" cannot replicate into relation with row-level security enabled: \" %s \" " ,
GetUserNameFromId ( GetUserId ( ) , true ) ,
RelationGetRelationName ( rel ) ) ) ) ;
/*
* Start a transaction in the remote node in REPEATABLE READ mode . This
* ensures that both the replication slot we create ( see below ) and the
@ -1456,6 +1434,39 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
originname ) ) ) ;
}
/*
* Make sure that the copy command runs as the table owner , unless
* the user has opted out of that behaviour .
*/
run_as_owner = MySubscription - > runasowner ;
if ( ! run_as_owner )
SwitchToUntrustedUser ( rel - > rd_rel - > relowner , & ucxt ) ;
/*
* Check that our table sync worker has permission to insert into the
* target table .
*/
aclresult = pg_class_aclcheck ( RelationGetRelid ( rel ) , GetUserId ( ) ,
ACL_INSERT ) ;
if ( aclresult ! = ACLCHECK_OK )
aclcheck_error ( aclresult ,
get_relkind_objtype ( rel - > rd_rel - > relkind ) ,
RelationGetRelationName ( rel ) ) ;
/*
* COPY FROM does not honor RLS policies . That is not a problem for
* subscriptions owned by roles with BYPASSRLS privilege ( or superuser ,
* who has it implicitly ) , but other roles should not be able to
* circumvent RLS . Disallow logical replication into RLS enabled
* relations for such roles .
*/
if ( check_enable_rls ( RelationGetRelid ( rel ) , InvalidOid , false ) = = RLS_ENABLED )
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " user \" %s \" cannot replicate into relation with row-level security enabled: \" %s \" " ,
GetUserNameFromId ( GetUserId ( ) , true ) ,
RelationGetRelationName ( rel ) ) ) ) ;
/* Now do the initial data copy */
PushActiveSnapshot ( GetTransactionSnapshot ( ) ) ;
copy_table ( rel ) ;
@ -1469,6 +1480,9 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
res - > err ) ) ) ;
walrcv_clear_result ( res ) ;
if ( ! run_as_owner )
RestoreUserContext ( & ucxt ) ;
table_close ( rel , NoLock ) ;
/* Make the copy visible. */