Re: SRF patch (was Re: [HACKERS] troubleshooting pointers) - Mailing list pgsql-patches
| From | Joe Conway |
|---|---|
| Subject | Re: SRF patch (was Re: [HACKERS] troubleshooting pointers) |
| Date | |
| Msg-id | 3CE343F9.5080208@joeconway.com Whole thread Raw |
| In response to | SRF patch (was Re: [HACKERS] troubleshooting pointers) (Joe Conway <mail@joeconway.com>) |
| List | pgsql-patches |
Joe Conway wrote:
>>
>
> Attached patch takes care of this case. It also passes my previous
> test
Sorry, I just noticed that I did not finish modifying the comments that
were cut-and-pasted from elsewhere. This patch includes better comments.
Joe
Index: src/backend/parser/parse_clause.c
===================================================================
RCS file: /opt/src/cvs/pgsql/src/backend/parser/parse_clause.c,v
retrieving revision 1.92
diff -c -r1.92 parse_clause.c
*** src/backend/parser/parse_clause.c 12 May 2002 23:43:03 -0000 1.92
--- src/backend/parser/parse_clause.c 15 May 2002 22:55:37 -0000
***************
*** 61,67 ****
static List *addTargetToSortList(TargetEntry *tle, List *sortlist,
List *targetlist, List *opname);
static bool exprIsInSortList(Node *expr, List *sortList, List *targetList);
!
/*
* transformFromClause -
--- 61,70 ----
static List *addTargetToSortList(TargetEntry *tle, List *sortlist,
List *targetlist, List *opname);
static bool exprIsInSortList(Node *expr, List *sortList, List *targetList);
! static void checkParameterVisibility(ParseState *pstate,
! RangeTblRef *rtr,
! RangeFunction *rangefunc,
! List *containedRels);
/*
* transformFromClause -
***************
*** 545,550 ****
--- 548,559 ----
rtr = transformRangeFunction(pstate, (RangeFunction *) n);
*containedRels = makeListi1(rtr->rtindex);
+
+ /*
+ * Make sure we've only been given valid parameters, i.e.
+ * we should not see vars from sibling FROM nodes.
+ */
+ checkParameterVisibility(pstate, rtr, (RangeFunction *) n, *containedRels);
return (Node *) rtr;
}
else if (IsA(n, JoinExpr))
***************
*** 1377,1380 ****
--- 1386,1445 ----
return true;
}
return false;
+ }
+
+ /* checkParameterVisibility()
+ * Make sure we don't try to access vars from
+ * sibling FROM nodes as RangeFunction parameters.
+ */
+ static void
+ checkParameterVisibility(ParseState *pstate, RangeTblRef *rtr, RangeFunction *rangefunc, List *containedRels)
+ {
+ FuncCall *funccallnode = (FuncCall *) rangefunc->funccallnode;
+ List *args = funccallnode->args;
+ List *save_namespace;
+ List *clause_varnos,
+ *l;
+
+ /*
+ * This is a tad tricky, for two reasons. First, the namespace that
+ * the function expression should see is just the any outer references
+ * from upper pstate levels. So, temporarily set this pstate's namespace
+ * accordingly. (We need not check for refname conflicts, because
+ * transformFromClauseItem() already did.) NOTE: this code is OK only
+ * because a RangeFunction can't legally alter the namespace by causing
+ * implicit relation refs to be added.
+ */
+ save_namespace = pstate->p_namespace;
+ pstate->p_namespace = makeList1(rtr);
+
+ /* transform the list of arguments */
+ foreach(args, funccallnode->args)
+ {
+ lfirst(args) = transformExpr(pstate, (Node *) lfirst(args));
+
+ /*
+ * Second, we need to check that the function parameters don't refer
+ * to any other rels. It could do that despite our hack on the namespace
+ * if it uses fully-qualified names. So, grovel through the transformed
+ * clause and make sure there are no bogus references. (Outer references
+ * are OK, and are ignored here.)
+ *
+ */
+
+ clause_varnos = pull_varnos(lfirst(args));
+ foreach(l, clause_varnos)
+ {
+ int varno = lfirsti(l);
+
+ if (!intMember(varno, containedRels))
+ {
+ elog(ERROR, "Function relation in FROM clause may not refer to other relation, \"%s\"",
+ rt_fetch(varno, pstate->p_rtable)->eref->aliasname);
+ }
+ }
+ freeList(clause_varnos);
+
+ }
+ pstate->p_namespace = save_namespace;
}
pgsql-patches by date: