*** pgsql/src/backend/parser/parse_clause.c 2009/01/01 17:23:45 1.185 --- pgsql/src/backend/parser/parse_clause.c 2009/01/22 20:16:05 1.186 *************** *** 8,14 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.184 2008/12/31 23:42:56 tgl Exp $ * *------------------------------------------------------------------------- */ --- 8,14 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.185 2009/01/01 17:23:45 momjian Exp $ * *------------------------------------------------------------------------- */ *************** static void extractRemainingColumns(List *** 53,58 **** --- 53,59 ---- List *src_colnames, List *src_colvars, List **res_colnames, List **res_colvars); static Node *transformJoinUsingClause(ParseState *pstate, + RangeTblEntry *leftRTE, RangeTblEntry *rightRTE, List *leftVars, List *rightVars); static Node *transformJoinOnClause(ParseState *pstate, JoinExpr *j, RangeTblEntry *l_rte, *************** setTargetTable(ParseState *pstate, Range *** 194,201 **** * * If we find an explicit reference to the rel later during parse * analysis, we will add the ACL_SELECT bit back again; see ! * scanRTEForColumn (for simple field references), ExpandColumnRefStar ! * (for foo.*) and ExpandAllTables (for *). */ rte->requiredPerms = requiredPerms; --- 195,201 ---- * * If we find an explicit reference to the rel later during parse * analysis, we will add the ACL_SELECT bit back again; see ! * markVarForSelectPriv and its callers. */ rte->requiredPerms = requiredPerms; *************** extractRemainingColumns(List *common_col *** 305,311 **** * Result is a transformed qualification expression. */ static Node * ! transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) { Node *result = NULL; ListCell *lvars, --- 305,313 ---- * Result is a transformed qualification expression. */ static Node * ! transformJoinUsingClause(ParseState *pstate, ! RangeTblEntry *leftRTE, RangeTblEntry *rightRTE, ! List *leftVars, List *rightVars) { Node *result = NULL; ListCell *lvars, *************** transformJoinUsingClause(ParseState *pst *** 315,331 **** * We cheat a little bit here by building an untransformed operator tree * whose leaves are the already-transformed Vars. This is OK because * transformExpr() won't complain about already-transformed subnodes. */ forboth(lvars, leftVars, rvars, rightVars) { ! Node *lvar = (Node *) lfirst(lvars); ! Node *rvar = (Node *) lfirst(rvars); A_Expr *e; e = makeSimpleA_Expr(AEXPR_OP, "=", copyObject(lvar), copyObject(rvar), -1); if (result == NULL) result = (Node *) e; else --- 317,341 ---- * We cheat a little bit here by building an untransformed operator tree * whose leaves are the already-transformed Vars. This is OK because * transformExpr() won't complain about already-transformed subnodes. + * However, this does mean that we have to mark the columns as requiring + * SELECT privilege for ourselves; transformExpr() won't do it. */ forboth(lvars, leftVars, rvars, rightVars) { ! Var *lvar = (Var *) lfirst(lvars); ! Var *rvar = (Var *) lfirst(rvars); A_Expr *e; + /* Require read access to the join variables */ + markVarForSelectPriv(pstate, lvar, leftRTE); + markVarForSelectPriv(pstate, rvar, rightRTE); + + /* Now create the lvar = rvar join condition */ e = makeSimpleA_Expr(AEXPR_OP, "=", copyObject(lvar), copyObject(rvar), -1); + /* And combine into an AND clause, if multiple join columns */ if (result == NULL) result = (Node *) e; else *************** transformFromClauseItem(ParseState *psta *** 728,733 **** --- 738,744 ---- *r_colvars, *res_colvars; RangeTblEntry *rte; + int k; /* * Recursively process the left and right subtrees *************** transformFromClauseItem(ParseState *psta *** 912,917 **** --- 923,930 ---- } j->quals = transformJoinUsingClause(pstate, + l_rte, + r_rte, l_usingvars, r_usingvars); } *************** transformFromClauseItem(ParseState *psta *** 972,977 **** --- 985,996 ---- *top_rte = rte; *top_rti = j->rtindex; + /* make a matching link to the JoinExpr for later use */ + for (k = list_length(pstate->p_joinexprs) + 1; k < j->rtindex; k++) + pstate->p_joinexprs = lappend(pstate->p_joinexprs, NULL); + pstate->p_joinexprs = lappend(pstate->p_joinexprs, j); + Assert(list_length(pstate->p_joinexprs) == j->rtindex); + /* * Prepare returned namespace list. If the JOIN has an alias then it * hides the contained RTEs as far as the relnamespace goes;