Index: src/backend/parser/analyze.c
===================================================================
*** src/backend/parser/analyze.c	(revision 1)
--- src/backend/parser/analyze.c	(working copy)
***************
*** 27,32 ****
--- 27,33 ----
  #include "catalog/pg_type.h"
  #include "nodes/makefuncs.h"
  #include "nodes/nodeFuncs.h"
+ #include "optimizer/tlist.h"
  #include "optimizer/var.h"
  #include "parser/analyze.h"
  #include "parser/parse_agg.h"
***************
*** 267,272 ****
--- 268,338 ----
  }
  
  /*
+  * applyColumnPrivs()
+  *     construct rte->cols_sel and rte->cols_mod for Column-level
+  *     privileges.
+  */
+ static bool
+ applyColumnPrivsWalker(Node *node, ParseState *pstate)
+ {
+ 	if (!node)
+ 		return false;
+ 
+ 	if (IsA(node, Var))
+ 	{
+ 		RangeTblEntry *rte;
+ 		Var *v = (Var *) node;
+ 		int lv;
+ 
+ 		for (lv = v->varlevelsup; lv > 0; lv--)
+ 		{
+ 			Assert(pstate->parentParseState != NULL);
+ 			pstate = pstate->parentParseState;
+ 		}
+ 
+ 		rte = rt_fetch(v->varno, pstate->p_rtable);
+ 		Assert(IsA(rte, RangeTblEntry));
+ 
+ 		if (rte->rtekind == RTE_RELATION)
+ 		{
+ 			rte->cols_sel = lappend_int(rte->cols_sel, v->varattno);
+ 		}
+ 		else if (rte->rtekind == RTE_JOIN)
+ 		{
+ 			node = list_nth(rte->joinaliasvars, v->varattno - 1);
+ 
+ 			applyColumnPrivsWalker(node, pstate);
+ 		}
+ 	}
+ 	else if (IsA(node, SortGroupClause))
+ 		return false;
+ 
+ 	return expression_tree_walker(node, applyColumnPrivsWalker, (void *) pstate);
+ }
+ 
+ static void
+ applyColumnPrivs(Query *query, ParseState *pstate)
+ {
+ 	ListCell *l;
+ 
+ 	if (query->commandType != CMD_SELECT)
+ 	{
+ 		RangeTblEntry *rte
+ 			= rt_fetch(query->resultRelation, query->rtable);
+ 
+ 		foreach (l, query->targetList)
+ 		{
+ 			TargetEntry *tle = lfirst(l);
+ 
+ 			Assert(IsA(tle, TargetEntry));
+ 			rte->cols_mod = lappend_int(rte->cols_mod, tle->resno);
+ 		}
+ 	}
+ 	query_tree_walker(query, applyColumnPrivsWalker, (void *) pstate,
+ 					  QTW_IGNORE_JOINALIASES);
+ }
+ 
+ /*
   * transformDeleteStmt -
   *	  transforms a Delete Statement
   */
***************
*** 683,688 ****
--- 749,756 ----
  				 parser_errposition(pstate,
  									locate_windowfunc((Node *) qry))));
  
+ 	applyColumnPrivs(qry, pstate);
+ 
  	return qry;
  }
  
***************
*** 876,881 ****
--- 944,951 ----
  		transformLockingClause(pstate, qry, (LockingClause *) lfirst(l));
  	}
  
+ 	applyColumnPrivs(qry, pstate);
+ 
  	return qry;
  }
  
***************
*** 1716,1721 ****
--- 1786,1793 ----
  	if (origTargetList != NULL)
  		elog(ERROR, "UPDATE target count mismatch --- internal error");
  
+ 	applyColumnPrivs(qry, pstate);
+ 
  	return qry;
  }
  
Index: src/backend/parser/parse_relation.c
===================================================================
*** src/backend/parser/parse_relation.c	(revision 2)
--- src/backend/parser/parse_relation.c	(working copy)
***************
*** 479,485 ****
  			result = (Node *) make_var(pstate, rte, attnum, location);
  			/* Require read access */
  			rte->requiredPerms |= ACL_SELECT;
- 			rte->cols_sel = lappend_int(rte->cols_sel,attnum);
  		}
  	}
  
--- 479,484 ----
***************
*** 508,514 ****
  				result = (Node *) make_var(pstate, rte, attnum, location);
  				/* Require read access */
  				rte->requiredPerms |= ACL_SELECT;
- 				rte->cols_sel = lappend_int(rte->cols_sel,attnum);
  			}
  		}
  	}
--- 507,512 ----
***************
*** 1749,1762 ****
  	expandTupleDesc(rel->rd_att, rte->eref, rtindex, sublevels_up,
  					location, include_dropped,
  					colnames, colvars);
- 
- 	for (attrno = 0; attrno < rel->rd_att->natts; attrno++)
- 	{
- 		Form_pg_attribute attr = rel->rd_att->attrs[attrno];
- 
- 		if (!attr->attisdropped)
- 			rte->cols_sel = lappend_int(rte->cols_sel, attrno+1);
- 	}
  	relation_close(rel, AccessShareLock);
  }
  
--- 1747,1752 ----
Index: src/backend/parser/parse_target.c
===================================================================
*** src/backend/parser/parse_target.c	(revision 2)
--- src/backend/parser/parse_target.c	(working copy)
***************
*** 372,378 ****
  	attrtype = attnumTypeId(rd, attrno);
  	attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod;
  
- 	pstate->p_target_rangetblentry->cols_mod = lappend_int(pstate->p_target_rangetblentry->cols_mod, attrno);
  
  	/*
  	 * If the expression is a DEFAULT placeholder, insert the attribute's
--- 372,377 ----
***************
*** 785,791 ****
  			col->location = -1;
  			cols = lappend(cols, col);
  			*attrnos = lappend_int(*attrnos, i + 1);
- 			pstate->p_target_rangetblentry->cols_mod = lappend_int(pstate->p_target_rangetblentry->cols_mod, i + 1);
  		}
  	}
  	else
--- 784,789 ----
***************
*** 842,848 ****
  			}
  
  			*attrnos = lappend_int(*attrnos, attrno);
- 			pstate->p_target_rangetblentry->cols_mod = lappend_int(pstate->p_target_rangetblentry->cols_mod, attrno);
  		}
  	}
  
--- 840,845 ----
Index: src/backend/catalog/aclchk.c
===================================================================
*** src/backend/catalog/aclchk.c	(revision 2)
--- src/backend/catalog/aclchk.c	(working copy)
***************
*** 2291,2296 ****
--- 2291,2302 ----
  
  	pfree(acl);
  
+ 	elog(NOTICE, "%s: %s.%s required: %04x allowed: %04x",
+ 		 __FUNCTION__,
+ 		 NameStr(classForm->relname),
+ 		 NameStr(((Form_pg_attribute) GETSTRUCT(attTuple))->attname),
+ 		 mask, result);
+ 
  	/* if we have a detoasted copy, free it */
  	if (colacl && (Pointer) colacl != DatumGetPointer(colaclDatum))
  		pfree(colacl);
