*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
***************
*** 1651,1656 **** _copyFromExpr(FromExpr *from)
--- 1651,1657 ----
  
  	COPY_NODE_FIELD(fromlist);
  	COPY_NODE_FIELD(quals);
+ 	COPY_SCALAR_FIELD(security_view);
  
  	return newnode;
  }
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
***************
*** 730,735 **** _equalFromExpr(FromExpr *a, FromExpr *b)
--- 730,736 ----
  {
  	COMPARE_NODE_FIELD(fromlist);
  	COMPARE_NODE_FIELD(quals);
+ 	COMPARE_SCALAR_FIELD(security_view);
  
  	return true;
  }
*** a/src/backend/nodes/makefuncs.c
--- b/src/backend/nodes/makefuncs.c
***************
*** 148,153 **** makeFromExpr(List *fromlist, Node *quals)
--- 148,154 ----
  
  	f->fromlist = fromlist;
  	f->quals = quals;
+ 	f->security_view = false;
  	return f;
  }
  
*** a/src/backend/nodes/outfuncs.c
--- b/src/backend/nodes/outfuncs.c
***************
*** 1329,1334 **** _outFromExpr(StringInfo str, FromExpr *node)
--- 1329,1335 ----
  
  	WRITE_NODE_FIELD(fromlist);
  	WRITE_NODE_FIELD(quals);
+ 	WRITE_BOOL_FIELD(security_view);
  }
  
  /*****************************************************************************
*** a/src/backend/nodes/readfuncs.c
--- b/src/backend/nodes/readfuncs.c
***************
*** 1109,1114 **** _readFromExpr(void)
--- 1109,1115 ----
  
  	READ_NODE_FIELD(fromlist);
  	READ_NODE_FIELD(quals);
+ 	READ_BOOL_FIELD(security_view);
  
  	READ_DONE();
  }
*** a/src/backend/optimizer/plan/initsplan.c
--- b/src/backend/optimizer/plan/initsplan.c
***************
*** 718,723 **** make_outerjoininfo(PlannerInfo *root,
--- 718,779 ----
   *****************************************************************************/
  
  /*
+  * expand_relids_on_view
+  *
+  * It expands the given relids when it tries to reference a part of relations
+  * within security views. If FromExpr->security_view is true, it means current
+  * user didn't have privileges to access underlaying tables without views.
+  * If user given function takes arguments which references only one-side of
+  * the join loop, optimization may distribute the function node into inside
+  * of the join. It has a possibility to leak contents of invisible tuples to
+  * be filtered using views.
+  */
+ static Relids
+ expand_relids_on_view(Node *jtnode, Relids relids)
+ {
+     if (IsA(jtnode, FromExpr))
+ 	{
+ 		FromExpr   *f = (FromExpr *) jtnode;
+ 		ListCell   *l;
+ 
+ 		foreach (l, f->fromlist)
+ 		{
+ 			if (f->security_view)
+ 			{
+ 				/*
+ 				 * All the node under the FromExpr with security_view = true
+ 				 * are originally come from a view with underlaying tables
+ 				 * which are not accessable from a person executing the query.
+ 				 * So, if the given clause depends on a part of the relations,
+ 				 * we expand its dependency into whole of the security view.
+ 				 */
+ 				Relids	temp = get_relids_in_jointree((Node *)lfirst(l), false);
+ 
+ 				if (bms_overlap(relids, temp))
+ 					relids = bms_add_members(relids, temp);
+ 			}
+ 			else
+ 			{
+ 				relids = expand_relids_on_view((Node *)lfirst(l), relids);
+ 			}
+ 		}
+ 	}
+ 	else if (IsA(jtnode, JoinExpr))
+ 	{
+ 		JoinExpr   *j = (JoinExpr *) jtnode;
+ 
+ 		relids = expand_relids_on_view(j->larg, relids);
+ 		relids = expand_relids_on_view(j->rarg, relids);
+ 	}
+ 	else if (!IsA(jtnode, RangeTblRef))
+ 	{
+ 		elog(ERROR, "unrecognized node type: %d", (int) nodeTag(jtnode));
+ 	}
+ 
+ 	return relids;
+ }
+ 
+ /*
   * distribute_qual_to_rels
   *	  Add clause information to either the baserestrictinfo or joininfo list
   *	  (depending on whether the clause is a join) of each base relation
***************
*** 780,785 **** distribute_qual_to_rels(PlannerInfo *root, Node *clause,
--- 836,847 ----
  		elog(ERROR, "JOIN qualification cannot refer to other relations");
  
  	/*
+ 	 * Ensure user given quals not to come into join loop
+ 	 */
+ 	if (contain_functions_expr(clause))
+ 		relids = expand_relids_on_view((Node *)root->parse->jointree, relids);
+ 
+ 	/*
  	 * If the clause is variable-free, our normal heuristic for pushing it
  	 * down to just the mentioned rels doesn't work, because there are none.
  	 *
*** a/src/backend/optimizer/prep/prepjointree.c
--- b/src/backend/optimizer/prep/prepjointree.c
***************
*** 34,39 ****
--- 34,40 ----
  #include "parser/parse_relation.h"
  #include "parser/parsetree.h"
  #include "rewrite/rewriteManip.h"
+ #include "utils/acl.h"
  
  
  typedef struct pullup_replace_vars_context
***************
*** 601,606 **** pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
--- 602,608 ----
  	PlannerInfo *subroot;
  	int			rtoffset;
  	pullup_replace_vars_context rvcontext;
+ 	List	   *tempList;
  	ListCell   *lc;
  
  	/*
***************
*** 829,834 **** pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
--- 831,853 ----
  	Assert(subroot->placeholder_list == NIL);
  
  	/*
+ 	 * In the case when the subquery came from a view, we have to disable
+ 	 * a part of optimization for the security reason.
+ 	 * If user provides a function with side-effects in WHERE clause and
+ 	 * it depends on a part of relations within a view, contents of the
+ 	 * invisible tuples might leak somewhere via user given functions.
+ 	 * When FromExpr->security_view is true, it prevents these functions
+ 	 * are distributed into inside of the subquery.
+ 	 * We assume it is harmless, if current user has enough privileges
+ 	 * on the underlaying tables.
+ 	 */
+ 	tempList = copyObject(subquery->rtable);
+ 	foreach (lc, tempList)
+ 		((RangeTblEntry *) lfirst(lc))->checkAsUser = InvalidOid;
+ 	if (check_relation_privileges(tempList, false) != ACLCHECK_OK)
+ 		subquery->jointree->security_view = true;
+ 
+ 	/*
  	 * Miscellaneous housekeeping.
  	 *
  	 * Although replace_rte_variables() faithfully updated parse->hasSubLinks
*** a/src/backend/optimizer/util/clauses.c
--- b/src/backend/optimizer/util/clauses.c
***************
*** 86,91 **** static bool contain_subplans_walker(Node *node, void *context);
--- 86,92 ----
  static bool contain_mutable_functions_walker(Node *node, void *context);
  static bool contain_volatile_functions_walker(Node *node, void *context);
  static bool contain_nonstrict_functions_walker(Node *node, void *context);
+ static bool contain_functions_expr_walker(Node *node, void *context);
  static Relids find_nonnullable_rels_walker(Node *node, bool top_level);
  static List *find_nonnullable_vars_walker(Node *node, bool top_level);
  static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK);
***************
*** 1116,1121 **** contain_nonstrict_functions_walker(Node *node, void *context)
--- 1117,1149 ----
  								  context);
  }
  
+ /*****************************************************************************
+  *		Check clauses for function expr
+  *****************************************************************************/
+ 
+ /*
+  * contain_functions_expr
+  *		Recursively search for functions expr within a clause.
+  *
+  * Returns true if FuncExpr is found.
+  */
+ bool
+ contain_functions_expr(Node *clause)
+ {
+ 	return contain_functions_expr_walker(clause, NULL);
+ }
+ 
+ static bool
+ contain_functions_expr_walker(Node *node, void *context)
+ {
+ 	if (node == NULL)
+ 		return false;
+ 
+ 	if (IsA(node, FuncExpr))
+ 		return true;
+ 
+ 	return expression_tree_walker(node, contain_functions_expr_walker, context);
+ }
  
  /*
   * find_nonnullable_rels
*** a/src/include/nodes/primnodes.h
--- b/src/include/nodes/primnodes.h
***************
*** 1207,1212 **** typedef struct FromExpr
--- 1207,1213 ----
  	NodeTag		type;
  	List	   *fromlist;		/* List of join subtrees */
  	Node	   *quals;			/* qualifiers on join, if any */
+ 	bool		security_view;	/* true, if leading FromExpr of security view */
  } FromExpr;
  
  #endif   /* PRIMNODES_H */
*** a/src/include/optimizer/clauses.h
--- b/src/include/optimizer/clauses.h
***************
*** 67,72 **** extern bool contain_subplans(Node *clause);
--- 67,73 ----
  extern bool contain_mutable_functions(Node *clause);
  extern bool contain_volatile_functions(Node *clause);
  extern bool contain_nonstrict_functions(Node *clause);
+ extern bool contain_functions_expr(Node *clause);
  extern Relids find_nonnullable_rels(Node *clause);
  extern List *find_nonnullable_vars(Node *clause);
  extern List *find_forced_null_vars(Node *clause);
