Commit e67867b2 authored by Tom Lane's avatar Tom Lane

Allow AS to be omitted when specifying an output column name in SELECT

(or RETURNING), but only when the output name is not any SQL keyword.
This seems as close as we can get to the standard's syntax without a
great deal of thrashing.  Original patch by Hiroshi Saito, amended by me.
parent cc80f0a3
<!-- $PostgreSQL: pgsql/doc/src/sgml/queries.sgml,v 1.44 2007/02/01 19:10:24 momjian Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/queries.sgml,v 1.45 2008/02/15 22:17:06 tgl Exp $ -->
<chapter id="queries"> <chapter id="queries">
<title>Queries</title> <title>Queries</title>
...@@ -491,7 +491,7 @@ FROM <replaceable>table_reference</replaceable> AS <replaceable>alias</replaceab ...@@ -491,7 +491,7 @@ FROM <replaceable>table_reference</replaceable> AS <replaceable>alias</replaceab
<synopsis> <synopsis>
FROM <replaceable>table_reference</replaceable> <replaceable>alias</replaceable> FROM <replaceable>table_reference</replaceable> <replaceable>alias</replaceable>
</synopsis> </synopsis>
The <literal>AS</literal> key word is noise. The <literal>AS</literal> key word is optional noise.
<replaceable>alias</replaceable> can be any identifier. <replaceable>alias</replaceable> can be any identifier.
</para> </para>
...@@ -1040,13 +1040,32 @@ SELECT a AS value, b + c AS sum FROM ... ...@@ -1040,13 +1040,32 @@ SELECT a AS value, b + c AS sum FROM ...
</para> </para>
<para> <para>
If no output column name is specified using <literal>AS</>, the system assigns a If no output column name is specified using <literal>AS</>,
default name. For simple column references, this is the name of the the system assigns a default column name. For simple column references,
referenced column. For function this is the name of the referenced column. For function
calls, this is the name of the function. For complex expressions, calls, this is the name of the function. For complex expressions,
the system will generate a generic name. the system will generate a generic name.
</para> </para>
<para>
The <literal>AS</> keyword is optional, but only if the new column
name does not match any
<productname>PostgreSQL</productname> keyword (see <xref
linkend="sql-keywords-appendix">). To avoid an accidental match to
a keyword, you can double-quote the column name. For example,
<literal>VALUE</> is a keyword, so this does not work:
<programlisting>
SELECT a value, b + c AS sum FROM ...
</programlisting>
but this does:
<programlisting>
SELECT a "value", b + c AS sum FROM ...
</programlisting>
For protection against possible
future keyword additions, it is recommended that you always either
write <literal>AS</literal> or double-quote the output column name.
</para>
<note> <note>
<para> <para>
The naming of output columns here is different from that done in The naming of output columns here is different from that done in
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/delete.sgml,v 1.32 2007/11/28 15:42:31 petere Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/delete.sgml,v 1.33 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -23,7 +23,7 @@ PostgreSQL documentation ...@@ -23,7 +23,7 @@ PostgreSQL documentation
DELETE FROM [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <replaceable class="parameter">alias</replaceable> ] DELETE FROM [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <replaceable class="parameter">alias</replaceable> ]
[ USING <replaceable class="PARAMETER">usinglist</replaceable> ] [ USING <replaceable class="PARAMETER">usinglist</replaceable> ]
[ WHERE <replaceable class="PARAMETER">condition</replaceable> | WHERE CURRENT OF <replaceable class="PARAMETER">cursor_name</replaceable> ] [ WHERE <replaceable class="PARAMETER">condition</replaceable> | WHERE CURRENT OF <replaceable class="PARAMETER">cursor_name</replaceable> ]
[ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] ] [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ [ AS ] <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/insert.sgml,v 1.35 2007/01/31 23:26:04 momjian Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/insert.sgml,v 1.36 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -22,7 +22,7 @@ PostgreSQL documentation ...@@ -22,7 +22,7 @@ PostgreSQL documentation
<synopsis> <synopsis>
INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) ] INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) ]
{ DEFAULT VALUES | VALUES ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) [, ...] | <replaceable class="PARAMETER">query</replaceable> } { DEFAULT VALUES | VALUES ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) [, ...] | <replaceable class="PARAMETER">query</replaceable> }
[ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] ] [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ [ AS ] <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.102 2007/11/28 15:42:31 petere Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.103 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -21,7 +21,7 @@ PostgreSQL documentation ...@@ -21,7 +21,7 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replaceable> [, ...] ) ] ] SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replaceable> [, ...] ) ] ]
* | <replaceable class="parameter">expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] * | <replaceable class="parameter">expression</replaceable> [ [ AS ] <replaceable class="parameter">output_name</replaceable> ] [, ...]
[ FROM <replaceable class="parameter">from_item</replaceable> [, ...] ] [ FROM <replaceable class="parameter">from_item</replaceable> [, ...] ]
[ WHERE <replaceable class="parameter">condition</replaceable> ] [ WHERE <replaceable class="parameter">condition</replaceable> ]
[ GROUP BY <replaceable class="parameter">expression</replaceable> [, ...] ] [ GROUP BY <replaceable class="parameter">expression</replaceable> [, ...] ]
...@@ -477,23 +477,45 @@ HAVING <replaceable class="parameter">condition</replaceable> ...@@ -477,23 +477,45 @@ HAVING <replaceable class="parameter">condition</replaceable>
<literal>SELECT</> and <literal>FROM</>) specifies expressions <literal>SELECT</> and <literal>FROM</>) specifies expressions
that form the output rows of the <command>SELECT</command> that form the output rows of the <command>SELECT</command>
statement. The expressions can (and usually do) refer to columns statement. The expressions can (and usually do) refer to columns
computed in the <literal>FROM</> clause. Using the clause computed in the <literal>FROM</> clause.
<literal>AS <replaceable </para>
class="parameter">output_name</replaceable></literal>, another
name can be specified for an output column. This name is <para>
primarily used to label the column for display. It can also be Just as in a table, every output column of a <command>SELECT</command>
used to refer to the column's value in <literal>ORDER BY</> and has a name. In a simple <command>SELECT</command> this name is just
<literal>GROUP BY</> clauses, but not in the <literal>WHERE</> or used to label the column for display, but when the <command>SELECT</>
<literal>HAVING</> clauses; there you must write out the is a sub-query of a larger query, the name is seen by the larger query
expression instead. as the column name of the virtual table produced by the sub-query.
To specify the name to use for an output column, write
<literal>AS</> <replaceable class="parameter">output_name</replaceable>
after the column's expression. (You can omit <literal>AS</literal>,
but only if the desired output name does not match any
<productname>PostgreSQL</productname> keyword (see <xref
linkend="sql-keywords-appendix">). For protection against possible
future keyword additions, it is recommended that you always either
write <literal>AS</literal> or double-quote the output name.)
If you do not specify a column name, a name is chosen automatically
by <productname>PostgreSQL</productname>. If the column's expression
is a simple column reference then the chosen name is the same as that
column's name; in more complex cases a generated name looking like
<literal>?column<replaceable>N</>?</literal> is usually chosen.
</para>
<para>
An output column's name can be used to refer to the column's value in
<literal>ORDER BY</> and <literal>GROUP BY</> clauses, but not in the
<literal>WHERE</> or <literal>HAVING</> clauses; there you must write
out the expression instead.
</para> </para>
<para> <para>
Instead of an expression, <literal>*</literal> can be written in Instead of an expression, <literal>*</literal> can be written in
the output list as a shorthand for all the columns of the selected the output list as a shorthand for all the columns of the selected
rows. Also, one can write <literal><replaceable rows. Also, you can write <literal><replaceable
class="parameter">table_name</replaceable>.*</literal> as a class="parameter">table_name</replaceable>.*</literal> as a
shorthand for the columns coming from just that table. shorthand for the columns coming from just that table. In these
cases it is not possible to specify new names with <literal>AS</>;
the output column names will be the same as the table columns' names.
</para> </para>
</refsect2> </refsect2>
...@@ -661,17 +683,17 @@ ORDER BY <replaceable class="parameter">expression</replaceable> [ ASC | DESC | ...@@ -661,17 +683,17 @@ ORDER BY <replaceable class="parameter">expression</replaceable> [ ASC | DESC |
<para> <para>
The ordinal number refers to the ordinal (left-to-right) position The ordinal number refers to the ordinal (left-to-right) position
of the result column. This feature makes it possible to define an of the output column. This feature makes it possible to define an
ordering on the basis of a column that does not have a unique ordering on the basis of a column that does not have a unique
name. This is never absolutely necessary because it is always name. This is never absolutely necessary because it is always
possible to assign a name to a result column using the possible to assign a name to an output column using the
<literal>AS</> clause. <literal>AS</> clause.
</para> </para>
<para> <para>
It is also possible to use arbitrary expressions in the It is also possible to use arbitrary expressions in the
<literal>ORDER BY</literal> clause, including columns that do not <literal>ORDER BY</literal> clause, including columns that do not
appear in the <command>SELECT</command> result list. Thus the appear in the <command>SELECT</command> output list. Thus the
following statement is valid: following statement is valid:
<programlisting> <programlisting>
SELECT name FROM distributors ORDER BY code; SELECT name FROM distributors ORDER BY code;
...@@ -684,8 +706,8 @@ SELECT name FROM distributors ORDER BY code; ...@@ -684,8 +706,8 @@ SELECT name FROM distributors ORDER BY code;
<para> <para>
If an <literal>ORDER BY</> expression is a simple name that If an <literal>ORDER BY</> expression is a simple name that
matches both a result column name and an input column name, matches both an output column name and an input column name,
<literal>ORDER BY</> will interpret it as the result column name. <literal>ORDER BY</> will interpret it as the output column name.
This is the opposite of the choice that <literal>GROUP BY</> will This is the opposite of the choice that <literal>GROUP BY</> will
make in the same situation. This inconsistency is made to be make in the same situation. This inconsistency is made to be
compatible with the SQL standard. compatible with the SQL standard.
...@@ -1135,16 +1157,25 @@ SELECT distributors.* WHERE distributors.name = 'Westward'; ...@@ -1135,16 +1157,25 @@ SELECT distributors.* WHERE distributors.name = 'Westward';
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>The <literal>AS</literal> Key Word</title> <title>Omitting the <literal>AS</literal> Key Word</title>
<para>
In the SQL standard, the optional key word <literal>AS</> can be
omitted before an output column name whenever the new column name
is a valid column name (that is, not the same as any reserved
keyword). <productname>PostgreSQL</productname> is slightly more
restrictive: <literal>AS</> is required if the new column name
matches any keyword at all, reserved or not. Recommended practice is
to use <literal>AS</> or double-quote output column names, to prevent
any possible conflict against future keyword additions.
</para>
<para> <para>
In the SQL standard, the optional key word <literal>AS</> is just In <literal>FROM</literal> items, both the standard and
noise and can be omitted without affecting the meaning. The <productname>PostgreSQL</productname> allow <literal>AS</> to
<productname>PostgreSQL</productname> parser requires this key be omitted before an alias that is an unreserved keyword. But
word when renaming output columns because the type extensibility this is impractical for output column names, because of syntactic
features lead to parsing ambiguities without it. ambiguities.
<literal>AS</literal> is optional in <literal>FROM</literal>
items, however.
</para> </para>
</refsect2> </refsect2>
...@@ -1153,7 +1184,7 @@ SELECT distributors.* WHERE distributors.name = 'Westward'; ...@@ -1153,7 +1184,7 @@ SELECT distributors.* WHERE distributors.name = 'Westward';
<para> <para>
In the SQL-92 standard, an <literal>ORDER BY</literal> clause can In the SQL-92 standard, an <literal>ORDER BY</literal> clause can
only use result column names or numbers, while a <literal>GROUP only use output column names or numbers, while a <literal>GROUP
BY</literal> clause can only use expressions based on input column BY</literal> clause can only use expressions based on input column
names. <productname>PostgreSQL</productname> extends each of names. <productname>PostgreSQL</productname> extends each of
these clauses to allow the other choice as well (but it uses the these clauses to allow the other choice as well (but it uses the
...@@ -1161,7 +1192,7 @@ SELECT distributors.* WHERE distributors.name = 'Westward'; ...@@ -1161,7 +1192,7 @@ SELECT distributors.* WHERE distributors.name = 'Westward';
<productname>PostgreSQL</productname> also allows both clauses to <productname>PostgreSQL</productname> also allows both clauses to
specify arbitrary expressions. Note that names appearing in an specify arbitrary expressions. Note that names appearing in an
expression will always be taken as input-column names, not as expression will always be taken as input-column names, not as
result-column names. output-column names.
</para> </para>
<para> <para>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/select_into.sgml,v 1.39 2007/01/09 02:14:10 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/select_into.sgml,v 1.40 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -21,7 +21,7 @@ PostgreSQL documentation ...@@ -21,7 +21,7 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replaceable> [, ...] ) ] ] SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replaceable> [, ...] ) ] ]
* | <replaceable class="PARAMETER">expression</replaceable> [ AS <replaceable class="PARAMETER">output_name</replaceable> ] [, ...] * | <replaceable class="PARAMETER">expression</replaceable> [ [ AS ] <replaceable class="PARAMETER">output_name</replaceable> ] [, ...]
INTO [ TEMPORARY | TEMP ] [ TABLE ] <replaceable class="PARAMETER">new_table</replaceable> INTO [ TEMPORARY | TEMP ] [ TABLE ] <replaceable class="PARAMETER">new_table</replaceable>
[ FROM <replaceable class="PARAMETER">from_item</replaceable> [, ...] ] [ FROM <replaceable class="PARAMETER">from_item</replaceable> [, ...] ]
[ WHERE <replaceable class="PARAMETER">condition</replaceable> ] [ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.45 2007/11/28 15:42:31 petere Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.46 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -25,7 +25,7 @@ UPDATE [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <rep ...@@ -25,7 +25,7 @@ UPDATE [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <rep
( <replaceable class="PARAMETER">column</replaceable> [, ...] ) = ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) } [, ...] ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) = ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) } [, ...]
[ FROM <replaceable class="PARAMETER">fromlist</replaceable> ] [ FROM <replaceable class="PARAMETER">fromlist</replaceable> ]
[ WHERE <replaceable class="PARAMETER">condition</replaceable> | WHERE CURRENT OF <replaceable class="PARAMETER">cursor_name</replaceable> ] [ WHERE <replaceable class="PARAMETER">condition</replaceable> | WHERE CURRENT OF <replaceable class="PARAMETER">cursor_name</replaceable> ]
[ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] ] [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ [ AS ] <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/sql.sgml,v 1.46 2007/02/16 03:50:29 momjian Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/sql.sgml,v 1.47 2008/02/15 22:17:06 tgl Exp $ -->
<chapter id="sql-intro"> <chapter id="sql-intro">
<title>SQL</title> <title>SQL</title>
...@@ -853,7 +853,7 @@ A &lt; B + 3. ...@@ -853,7 +853,7 @@ A &lt; B + 3.
<synopsis> <synopsis>
SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replaceable> [, ...] ) ] ] SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replaceable> [, ...] ) ] ]
* | <replaceable class="PARAMETER">expression</replaceable> [ AS <replaceable class="PARAMETER">output_name</replaceable> ] [, ...] * | <replaceable class="PARAMETER">expression</replaceable> [ [ AS ] <replaceable class="PARAMETER">output_name</replaceable> ] [, ...]
[ INTO [ TEMPORARY | TEMP ] [ TABLE ] <replaceable class="PARAMETER">new_table</replaceable> ] [ INTO [ TEMPORARY | TEMP ] [ TABLE ] <replaceable class="PARAMETER">new_table</replaceable> ]
[ FROM <replaceable class="PARAMETER">from_item</replaceable> [, ...] ] [ FROM <replaceable class="PARAMETER">from_item</replaceable> [, ...] ]
[ WHERE <replaceable class="PARAMETER">condition</replaceable> ] [ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.606 2008/02/07 21:07:55 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.607 2008/02/15 22:17:06 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -477,6 +477,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) ...@@ -477,6 +477,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
%nonassoc BETWEEN %nonassoc BETWEEN
%nonassoc IN_P %nonassoc IN_P
%left POSTFIXOP /* dummy for postfix Op rules */ %left POSTFIXOP /* dummy for postfix Op rules */
%nonassoc IDENT /* to support target_el without AS */
%left Op OPERATOR /* multi-character ops and user-defined operators */ %left Op OPERATOR /* multi-character ops and user-defined operators */
%nonassoc NOTNULL %nonassoc NOTNULL
%nonassoc ISNULL %nonassoc ISNULL
...@@ -8705,7 +8706,6 @@ target_list: ...@@ -8705,7 +8706,6 @@ target_list:
| target_list ',' target_el { $$ = lappend($1, $3); } | target_list ',' target_el { $$ = lappend($1, $3); }
; ;
/* AS is not optional because shift/red conflict with unary ops */
target_el: a_expr AS ColLabel target_el: a_expr AS ColLabel
{ {
$$ = makeNode(ResTarget); $$ = makeNode(ResTarget);
...@@ -8714,6 +8714,22 @@ target_el: a_expr AS ColLabel ...@@ -8714,6 +8714,22 @@ target_el: a_expr AS ColLabel
$$->val = (Node *)$1; $$->val = (Node *)$1;
$$->location = @1; $$->location = @1;
} }
/*
* We support omitting AS only for column labels that aren't
* any known keyword. There is an ambiguity against postfix
* operators: is "a ! b" an infix expression, or a postfix
* expression and a column label? We prefer to resolve this
* as an infix expression, which we accomplish by assigning
* IDENT a precedence higher than POSTFIXOP.
*/
| a_expr IDENT
{
$$ = makeNode(ResTarget);
$$->name = $2;
$$->indirection = NIL;
$$->val = (Node *)$1;
$$->location = @1;
}
| a_expr | a_expr
{ {
$$ = makeNode(ResTarget); $$ = makeNode(ResTarget);
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.360 2008/02/14 14:54:48 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.361 2008/02/15 22:17:06 tgl Exp $ */
/* Copyright comment */ /* Copyright comment */
%{ %{
...@@ -521,8 +521,9 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu ...@@ -521,8 +521,9 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu
%nonassoc OVERLAPS %nonassoc OVERLAPS
%nonassoc BETWEEN %nonassoc BETWEEN
%nonassoc IN_P %nonassoc IN_P
%left POSTFIXOP /* dummy for postfix Op rules */ %left POSTFIXOP /* dummy for postfix Op rules */
%left Op OPERATOR /* multi-character ops and user-defined operators */ %nonassoc IDENT /* to support target_el without AS */
%left Op OPERATOR /* multi-character ops and user-defined operators */
%nonassoc NOTNULL %nonassoc NOTNULL
%nonassoc ISNULL %nonassoc ISNULL
%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN %nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN
...@@ -4695,9 +4696,10 @@ target_list: target_list ',' target_el ...@@ -4695,9 +4696,10 @@ target_list: target_list ',' target_el
{ $$ = $1; } { $$ = $1; }
; ;
/* AS is not optional because shift/red conflict with unary ops */
target_el: a_expr AS ColLabel target_el: a_expr AS ColLabel
{ $$ = cat_str(3, $1, make_str("as"), $3); } { $$ = cat_str(3, $1, make_str("as"), $3); }
| a_expr IDENT
{ $$ = cat_str(3, $1, make_str("as"), $2); }
| a_expr | a_expr
{ $$ = $1; } { $$ = $1; }
| '*' | '*'
......
...@@ -2337,9 +2337,9 @@ begin ...@@ -2337,9 +2337,9 @@ begin
end loop; end loop;
return 5; return 5;
end;$$ language plpgsql; end;$$ language plpgsql;
ERROR: syntax error at or near "fought" ERROR: syntax error at or near "the"
LINE 1: select I fought the law, the law won LINE 1: select I fought the law, the law won
^ ^
QUERY: select I fought the law, the law won QUERY: select I fought the law, the law won
CONTEXT: SQL statement in PL/PgSQL function "bad_sql2" near line 3 CONTEXT: SQL statement in PL/PgSQL function "bad_sql2" near line 3
-- a RETURN expression is mandatory, except for void-returning -- a RETURN expression is mandatory, except for void-returning
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment