88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.108 2003/02/1305:53:46 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.109 2003/02/1320:45:21 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -383,7 +383,6 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
383383static RangeTblRef *
384384transformRangeSubselect (ParseState * pstate ,RangeSubselect * r )
385385{
386- List * save_namespace ;
387386List * parsetrees ;
388387Query * query ;
389388RangeTblEntry * rte ;
@@ -398,21 +397,10 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
398397elog (ERROR ,"sub-select in FROM must have an alias" );
399398
400399/*
401- * Analyze and transform the subquery.This is a bit tricky because
402- * we don't want the subquery to be able to see any FROM items already
403- * created in the current query (per SQL92, the scope of a FROM item
404- * does not include other FROM items).But it does need to be able to
405- * see any further-up parent states, so we can't just pass a null
406- * parent pstate link.So, temporarily make the current query level
407- * have an empty namespace.
400+ * Analyze and transform the subquery.
408401 */
409- save_namespace = pstate -> p_namespace ;
410- pstate -> p_namespace = NIL ;
411-
412402parsetrees = parse_analyze (r -> subquery ,pstate );
413403
414- pstate -> p_namespace = save_namespace ;
415-
416404/*
417405 * Check that we got something reasonable.Some of these conditions
418406 * are probably impossible given restrictions of the grammar, but
@@ -429,6 +417,25 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
429417if (query -> resultRelation != 0 || query -> into != NULL || query -> isPortal )
430418elog (ERROR ,"Subselect in FROM may not have SELECT INTO" );
431419
420+ /*
421+ * The subquery cannot make use of any variables from FROM items created
422+ * earlier in the current query. Per SQL92, the scope of a FROM item
423+ * does not include other FROM items. Formerly we hacked the namespace
424+ * so that the other variables weren't even visible, but it seems more
425+ * useful to leave them visible and give a specific error message.
426+ *
427+ * XXX this will need further work to support SQL99's LATERAL() feature,
428+ * wherein such references would indeed be legal.
429+ *
430+ * We can skip groveling through the subquery if there's not anything
431+ * visible in the current query. Also note that outer references are OK.
432+ */
433+ if (pstate -> p_namespace )
434+ {
435+ if (contain_vars_of_level ((Node * )query ,1 ))
436+ elog (ERROR ,"Subselect in FROM may not refer to other relations of same query level" );
437+ }
438+
432439/*
433440 * OK, build an RTE for the subquery.
434441 */
@@ -455,7 +462,6 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
455462{
456463Node * funcexpr ;
457464char * funcname ;
458- List * save_namespace ;
459465RangeTblEntry * rte ;
460466RangeTblRef * rtr ;
461467
@@ -464,31 +470,24 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
464470funcname = strVal (llast (((FuncCall * )r -> funccallnode )-> funcname ));
465471
466472/*
467- * Transform the raw FuncCall node. This is a bit tricky because we
468- * don't want the function expression to be able to see any FROM items
469- * already created in the current query (compare to
470- * transformRangeSubselect). But it does need to be able to see any
471- * further-up parent states. So, temporarily make the current query
472- * level have an empty namespace. NOTE: this code is OK only because
473- * the expression can't legally alter the namespace by causing
474- * implicit relation refs to be added.
473+ * Transform the raw FuncCall node.
475474 */
476- save_namespace = pstate -> p_namespace ;
477- pstate -> p_namespace = NIL ;
478-
479475funcexpr = transformExpr (pstate ,r -> funccallnode );
480476
481- pstate -> p_namespace = save_namespace ;
482-
483477/*
484- * We still need to check that the function parameters don't refer to
485- * any other rels.That could happen despite our hack on the
486- * namespace if fully-qualified names are used. So, check there are
487- * no local Var references in the transformed expression. (Outer
488- * references are OK, and are ignored here.)
478+ * The function parameters cannot make use of any variables from other
479+ * FROM items. (Compare to transformRangeSubselect(); the coding is
480+ * different though because we didn't parse as a sub-select with its own
481+ * level of namespace.)
482+ *
483+ * XXX this will need further work to support SQL99's LATERAL() feature,
484+ * wherein such references would indeed be legal.
489485 */
490- if (!bms_is_empty (pull_varnos (funcexpr )))
491- elog (ERROR ,"FROM function expression may not refer to other relations of same query level" );
486+ if (pstate -> p_namespace )
487+ {
488+ if (contain_vars_of_level (funcexpr ,0 ))
489+ elog (ERROR ,"FROM function expression may not refer to other relations of same query level" );
490+ }
492491
493492/*
494493 * Disallow aggregate functions in the expression.(No reason to