mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Allow an alias to be attached to a JOIN ... USING
This allows something like SELECT ... FROM t1 JOIN t2 USING (a, b, c) AS x where x has the columns a, b, c and unlike a regular alias it does not hide the range variables of the tables being joined t1 and t2. Per SQL:2016 feature F404 "Range variable for common column names". Reviewed-by: Vik Fearing <vik.fearing@2ndquadrant.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://www.postgresql.org/message-id/flat/454638cf-d563-ab76-a585-2564428062af@2ndquadrant.com
This commit is contained in:
@ -2512,26 +2512,61 @@ static Node *
|
||||
transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem,
|
||||
int sublevels_up, int location)
|
||||
{
|
||||
Var *result;
|
||||
|
||||
/*
|
||||
* Build the appropriate referencing node. Note that if the RTE is a
|
||||
* function returning scalar, we create just a plain reference to the
|
||||
* function value, not a composite containing a single column. This is
|
||||
* pretty inconsistent at first sight, but it's what we've done
|
||||
* historically. One argument for it is that "rel" and "rel.*" mean the
|
||||
* same thing for composite relations, so why not for scalar functions...
|
||||
* Build the appropriate referencing node. Normally this can be a
|
||||
* whole-row Var, but if the nsitem is a JOIN USING alias then it contains
|
||||
* only a subset of the columns of the underlying join RTE, so that will
|
||||
* not work. Instead we immediately expand the reference into a RowExpr.
|
||||
* Since the JOIN USING's common columns are fully determined at this
|
||||
* point, there seems no harm in expanding it now rather than during
|
||||
* planning.
|
||||
*
|
||||
* Note that if the RTE is a function returning scalar, we create just a
|
||||
* plain reference to the function value, not a composite containing a
|
||||
* single column. This is pretty inconsistent at first sight, but it's
|
||||
* what we've done historically. One argument for it is that "rel" and
|
||||
* "rel.*" mean the same thing for composite relations, so why not for
|
||||
* scalar functions...
|
||||
*/
|
||||
result = makeWholeRowVar(nsitem->p_rte, nsitem->p_rtindex,
|
||||
sublevels_up, true);
|
||||
if (nsitem->p_names == nsitem->p_rte->eref)
|
||||
{
|
||||
Var *result;
|
||||
|
||||
/* location is not filled in by makeWholeRowVar */
|
||||
result->location = location;
|
||||
result = makeWholeRowVar(nsitem->p_rte, nsitem->p_rtindex,
|
||||
sublevels_up, true);
|
||||
|
||||
/* mark relation as requiring whole-row SELECT access */
|
||||
markVarForSelectPriv(pstate, result);
|
||||
/* location is not filled in by makeWholeRowVar */
|
||||
result->location = location;
|
||||
|
||||
return (Node *) result;
|
||||
/* mark relation as requiring whole-row SELECT access */
|
||||
markVarForSelectPriv(pstate, result);
|
||||
|
||||
return (Node *) result;
|
||||
}
|
||||
else
|
||||
{
|
||||
RowExpr *rowexpr;
|
||||
List *fields;
|
||||
|
||||
/*
|
||||
* We want only as many columns as are listed in p_names->colnames,
|
||||
* and we should use those names not whatever possibly-aliased names
|
||||
* are in the RTE. We needn't worry about marking the RTE for SELECT
|
||||
* access, as the common columns are surely so marked already.
|
||||
*/
|
||||
expandRTE(nsitem->p_rte, nsitem->p_rtindex,
|
||||
sublevels_up, location, false,
|
||||
NULL, &fields);
|
||||
rowexpr = makeNode(RowExpr);
|
||||
rowexpr->args = list_truncate(fields,
|
||||
list_length(nsitem->p_names->colnames));
|
||||
rowexpr->row_typeid = RECORDOID;
|
||||
rowexpr->row_format = COERCE_IMPLICIT_CAST;
|
||||
rowexpr->colnames = copyObject(nsitem->p_names->colnames);
|
||||
rowexpr->location = location;
|
||||
|
||||
return (Node *) rowexpr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user