diff options
Diffstat (limited to 'src/backend/parser/gram.y')
-rw-r--r-- | src/backend/parser/gram.y | 60 |
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; + } ; |