diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
new file mode 100644
index 61edde9..647ea77
*** a/src/backend/utils/adt/ri_triggers.c
--- b/src/backend/utils/adt/ri_triggers.c
*************** ri_PlanCheck(const char *querystr, int n
*** 2984,3001 ****
  	/* Switch to proper UID to perform check as */
  	GetUserIdAndSecContext(&save_userid, &save_sec_context);
  
- 	/*
- 	 * Row-level security should be disabled in the case where a foreign-key
- 	 * relation is queried to check existence of tuples that references the
- 	 * primary-key being modified.
- 	 */
  	temp_sec_context = save_sec_context | SECURITY_LOCAL_USERID_CHANGE;
- 	if (qkey->constr_queryno == RI_PLAN_CHECK_LOOKUPPK
- 		|| qkey->constr_queryno == RI_PLAN_CHECK_LOOKUPPK_FROM_PK
- 		|| qkey->constr_queryno == RI_PLAN_RESTRICT_DEL_CHECKREF
- 		|| qkey->constr_queryno == RI_PLAN_RESTRICT_UPD_CHECKREF)
- 		temp_sec_context |= SECURITY_ROW_LEVEL_DISABLED;
- 
  
  	SetUserIdAndSecContext(RelationGetForm(query_rel)->relowner,
  						   temp_sec_context);
--- 2984,2990 ----
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
new file mode 100644
index 525794f..d0bcff9
*** a/src/backend/utils/cache/plancache.c
--- b/src/backend/utils/cache/plancache.c
*************** CreateCachedPlan(Node *raw_parse_tree,
*** 204,211 ****
  	plansource->total_custom_cost = 0;
  	plansource->num_custom_plans = 0;
  	plansource->hasRowSecurity = false;
! 	plansource->rowSecurityDisabled = InRowLevelSecurityDisabled();
! 	plansource->row_security_env = row_security;
  	plansource->planUserId = InvalidOid;
  
  	MemoryContextSwitchTo(oldcxt);
--- 204,212 ----
  	plansource->total_custom_cost = 0;
  	plansource->num_custom_plans = 0;
  	plansource->hasRowSecurity = false;
! 	plansource->row_security_env = InLocalUserIdChange() &&
! 								   row_security == ROW_SECURITY_FORCE ?
! 								   ROW_SECURITY_ON : row_security;
  	plansource->planUserId = InvalidOid;
  
  	MemoryContextSwitchTo(oldcxt);
*************** RevalidateCachedQuery(CachedPlanSource *
*** 580,586 ****
  	if (!OidIsValid(plansource->planUserId))
  	{
  		plansource->planUserId = GetUserId();
! 		plansource->row_security_env = row_security;
  	}
  
  	/*
--- 581,588 ----
  	if (!OidIsValid(plansource->planUserId))
  	{
  		plansource->planUserId = GetUserId();
! 		plansource->row_security_env = InLocalUserIdChange() ? ROW_SECURITY_ON :
! 									   row_security;
  	}
  
  	/*
*************** RevalidateCachedQuery(CachedPlanSource *
*** 611,617 ****
  	 * setting has been changed.
  	 */
  	if (plansource->is_valid
- 		&& !plansource->rowSecurityDisabled
  		&& plansource->hasRowSecurity
  		&& (plansource->planUserId != GetUserId()
  			|| plansource->row_security_env != row_security))
--- 613,618 ----
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
new file mode 100644
index 5bf595c..6de266e
*** a/src/backend/utils/init/miscinit.c
--- b/src/backend/utils/init/miscinit.c
*************** GetAuthenticatedUserId(void)
*** 359,367 ****
   * where the called functions are really supposed to be side-effect-free
   * anyway, such as VACUUM/ANALYZE/REINDEX.
   *
-  * SECURITY_ROW_LEVEL_DISABLED indicates that we are inside an operation that
-  * needs to bypass row level security checks, for example FK checks.
-  *
   * Unlike GetUserId, GetUserIdAndSecContext does *not* Assert that the current
   * value of CurrentUserId is valid; nor does SetUserIdAndSecContext require
   * the new value to be valid.  In fact, these routines had better not
--- 359,364 ----
*************** InSecurityRestrictedOperation(void)
*** 404,418 ****
  	return (SecurityRestrictionContext & SECURITY_RESTRICTED_OPERATION) != 0;
  }
  
- /*
-  * InRowLevelSecurityDisabled - are we inside a RLS-disabled operation?
-  */
- bool
- InRowLevelSecurityDisabled(void)
- {
- 	return (SecurityRestrictionContext & SECURITY_ROW_LEVEL_DISABLED) != 0;
- }
- 
  
  /*
   * These are obsolete versions of Get/SetUserIdAndSecContext that are
--- 401,406 ----
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
new file mode 100644
index 8ebf424..c941b42
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
*************** static struct config_enum ConfigureNames
*** 3633,3639 ****
  	{
  		{"row_security", PGC_USERSET, CONN_AUTH_SECURITY,
  			gettext_noop("Enable row security."),
! 			gettext_noop("When enabled, row security will be applied to all users.")
  		},
  		&row_security,
  		ROW_SECURITY_ON, row_security_options,
--- 3633,3640 ----
  	{
  		{"row_security", PGC_USERSET, CONN_AUTH_SECURITY,
  			gettext_noop("Enable row security."),
! 			gettext_noop("When enabled, row security will be applied to all users."),
! 			GUC_NOT_WHILE_SEC_REST
  		},
  		&row_security,
  		ROW_SECURITY_ON, row_security_options,
diff --git a/src/backend/utils/misc/rls.c b/src/backend/utils/misc/rls.c
new file mode 100644
index 7b8d51d..a94b9a7
*** a/src/backend/utils/misc/rls.c
--- b/src/backend/utils/misc/rls.c
*************** check_enable_rls(Oid relid, Oid checkAsU
*** 63,75 ****
  	if (relid < FirstNormalObjectId)
  		return RLS_NONE;
  
- 	/*
- 	 * Check if we have been told to explicitly skip RLS (perhaps because this
- 	 * is a foreign key check)
- 	 */
- 	if (InRowLevelSecurityDisabled())
- 		return RLS_NONE;
- 
  	tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
  	if (!HeapTupleIsValid(tuple))
  		return RLS_NONE;
--- 63,68 ----
*************** check_enable_rls(Oid relid, Oid checkAsU
*** 99,105 ****
  	 * environment (in this case, what the current values of user_id and
  	 * row_security are).
  	 */
! 	if (row_security != ROW_SECURITY_FORCE
  		&& (pg_class_ownercheck(relid, user_id)))
  		return RLS_NONE_ENV;
  
--- 92,98 ----
  	 * environment (in this case, what the current values of user_id and
  	 * row_security are).
  	 */
! 	if ((InLocalUserIdChange() || row_security != ROW_SECURITY_FORCE)
  		&& (pg_class_ownercheck(relid, user_id)))
  		return RLS_NONE_ENV;
  
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
new file mode 100644
index e0cc69f..80ac732
*** a/src/include/miscadmin.h
--- b/src/include/miscadmin.h
*************** extern int	trace_recovery(int trace_leve
*** 286,292 ****
  /* flags to be OR'd to form sec_context */
  #define SECURITY_LOCAL_USERID_CHANGE	0x0001
  #define SECURITY_RESTRICTED_OPERATION	0x0002
- #define SECURITY_ROW_LEVEL_DISABLED		0x0004
  
  extern char *DatabasePath;
  
--- 286,291 ----
*************** extern void GetUserIdAndSecContext(Oid *
*** 305,311 ****
  extern void SetUserIdAndSecContext(Oid userid, int sec_context);
  extern bool InLocalUserIdChange(void);
  extern bool InSecurityRestrictedOperation(void);
- extern bool InRowLevelSecurityDisabled(void);
  extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context);
  extern void SetUserIdAndContext(Oid userid, bool sec_def_context);
  extern void InitializeSessionUserId(const char *rolename, Oid useroid);
--- 304,309 ----
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
new file mode 100644
index 90a0180..1c50f8d
*** a/src/include/utils/plancache.h
--- b/src/include/utils/plancache.h
*************** typedef struct CachedPlanSource
*** 111,117 ****
  	int			num_custom_plans;		/* number of plans included in total */
  	bool		hasRowSecurity; /* planned with row security? */
  	int			row_security_env;		/* row security setting when planned */
- 	bool		rowSecurityDisabled;	/* is row security disabled? */
  } CachedPlanSource;
  
  /*
--- 111,116 ----
