aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/gram.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/gram.y')
-rw-r--r--src/backend/parser/gram.y60
1 files changed, 51 insertions, 9 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 7ff36bc8422..8b1bad0d794 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -509,7 +509,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <ival> sub_type opt_materialized
%type <value> NumericOnly
%type <list> NumericOnly_list
-%type <alias> alias_clause opt_alias_clause
+%type <alias> alias_clause opt_alias_clause opt_alias_clause_for_join_using
%type <list> func_alias_clause
%type <sortby> sortby
%type <ielem> index_elem index_elem_options
@@ -12144,6 +12144,7 @@ joined_table:
n->larg = $1;
n->rarg = $4;
n->usingClause = NIL;
+ n->join_using_alias = NULL;
n->quals = NULL;
$$ = n;
}
@@ -12155,9 +12156,16 @@ joined_table:
n->larg = $1;
n->rarg = $4;
if ($5 != NULL && IsA($5, List))
- n->usingClause = (List *) $5; /* USING clause */
+ {
+ /* USING clause */
+ n->usingClause = linitial_node(List, castNode(List, $5));
+ n->join_using_alias = lsecond_node(Alias, castNode(List, $5));
+ }
else
- n->quals = $5; /* ON clause */
+ {
+ /* ON clause */
+ n->quals = $5;
+ }
$$ = n;
}
| table_ref JOIN table_ref join_qual
@@ -12169,9 +12177,16 @@ joined_table:
n->larg = $1;
n->rarg = $3;
if ($4 != NULL && IsA($4, List))
- n->usingClause = (List *) $4; /* USING clause */
+ {
+ /* USING clause */
+ n->usingClause = linitial_node(List, castNode(List, $4));
+ n->join_using_alias = lsecond_node(Alias, castNode(List, $4));
+ }
else
- n->quals = $4; /* ON clause */
+ {
+ /* ON clause */
+ n->quals = $4;
+ }
$$ = n;
}
| table_ref NATURAL join_type JOIN table_ref
@@ -12182,6 +12197,7 @@ joined_table:
n->larg = $1;
n->rarg = $5;
n->usingClause = NIL; /* figure out which columns later... */
+ n->join_using_alias = NULL;
n->quals = NULL; /* fill later */
$$ = n;
}
@@ -12194,6 +12210,7 @@ joined_table:
n->larg = $1;
n->rarg = $4;
n->usingClause = NIL; /* figure out which columns later... */
+ n->join_using_alias = NULL;
n->quals = NULL; /* fill later */
$$ = n;
}
@@ -12229,6 +12246,22 @@ opt_alias_clause: alias_clause { $$ = $1; }
;
/*
+ * The alias clause after JOIN ... USING only accepts the AS ColId spelling,
+ * per SQL standard. (The grammar could parse the other variants, but they
+ * don't seem to be useful, and it might lead to parser problems in the
+ * future.)
+ */
+opt_alias_clause_for_join_using:
+ AS ColId
+ {
+ $$ = makeNode(Alias);
+ $$->aliasname = $2;
+ /* the column name list will be inserted later */
+ }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+/*
* func_alias_clause can include both an Alias and a coldeflist, so we make it
* return a 2-element list that gets disassembled by calling production.
*/
@@ -12272,15 +12305,24 @@ opt_outer: OUTER_P
/* JOIN qualification clauses
* Possibilities are:
- * USING ( column list ) allows only unqualified column names,
+ * USING ( column list ) [ AS alias ]
+ * allows only unqualified column names,
* which must match between tables.
* ON expr allows more general qualifications.
*
- * We return USING as a List node, while an ON-expr will not be a List.
+ * We return USING as a two-element List (the first item being a sub-List
+ * of the common column names, and the second either an Alias item or NULL).
+ * An ON-expr will not be a List, so it can be told apart that way.
*/
-join_qual: USING '(' name_list ')' { $$ = (Node *) $3; }
- | ON a_expr { $$ = $2; }
+join_qual: USING '(' name_list ')' opt_alias_clause_for_join_using
+ {
+ $$ = (Node *) list_make2($3, $5);
+ }
+ | ON a_expr
+ {
+ $$ = $2;
+ }
;