summaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_clause.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-01-26 16:18:42 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2013-01-26 16:18:42 -0500
commit2378d79ab29865f59245744beb8f04a3ce56d2ae (patch)
tree58b1624c0041c7ae85394b8d3b559f50b7ac6191 /src/backend/parser/parse_clause.c
parent8865fe0ad3e4260db0e67e2064200d96c0999fa0 (diff)
Make LATERAL implicit for functions in FROM.
The SQL standard does not have general functions-in-FROM, but it does allow UNNEST() there (see the <collection derived table> production), and the semantics of that are defined to include lateral references. So spec compliance requires allowing lateral references within UNNEST() even without an explicit LATERAL keyword. Rather than making UNNEST() a special case, it seems best to extend this flexibility to any function-in-FROM. We'll still allow LATERAL to be written explicitly for clarity's sake, but it's now a noise word in this context. In theory this change could result in a change in behavior of existing queries, by allowing what had been an outer reference in a function-in-FROM to be captured by an earlier FROM-item at the same level. However, all pre-9.3 PG releases have a bug that causes them to match variable references to earlier FROM-items in preference to outer references (and then throw an error). So no previously-working query could contain the type of ambiguity that would risk a change of behavior. Per a suggestion from Andrew Gierth, though I didn't use his patch.
Diffstat (limited to 'src/backend/parser/parse_clause.c')
-rw-r--r--src/backend/parser/parse_clause.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index dd78500aa93..b9655954cde 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -503,6 +503,7 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
{
Node *funcexpr;
char *funcname;
+ bool is_lateral;
RangeTblEntry *rte;
/*
@@ -514,12 +515,16 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
funcname = FigureColname(r->funccallnode);
/*
- * If the function is LATERAL, make lateral_only names of this level
- * visible to it. (LATERAL can't nest within a single pstate level, so we
- * don't need save/restore logic here.)
+ * We make lateral_only names of this level visible, whether or not the
+ * function is explicitly marked LATERAL. This is needed for SQL spec
+ * compliance in the case of UNNEST(), and seems useful on convenience
+ * grounds for all functions in FROM.
+ *
+ * (LATERAL can't nest within a single pstate level, so we don't need
+ * save/restore logic here.)
*/
Assert(!pstate->p_lateral_active);
- pstate->p_lateral_active = r->lateral;
+ pstate->p_lateral_active = true;
/*
* Transform the raw expression.
@@ -534,10 +539,16 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
assign_expr_collations(pstate, funcexpr);
/*
+ * Mark the RTE as LATERAL if the user said LATERAL explicitly, or if
+ * there are any lateral cross-references in it.
+ */
+ is_lateral = r->lateral || contain_vars_of_level(funcexpr, 0);
+
+ /*
* OK, build an RTE for the function.
*/
rte = addRangeTableEntryForFunction(pstate, funcname, funcexpr,
- r, r->lateral, true);
+ r, is_lateral, true);
/*
* If a coldeflist was supplied, ensure it defines a legal set of names