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.
This commit is contained in:
parent
cc80f0a340
commit
e67867b26c
@ -1,4 +1,4 @@
|
||||
<!-- $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">
|
||||
<title>Queries</title>
|
||||
@ -491,7 +491,7 @@ FROM <replaceable>table_reference</replaceable> AS <replaceable>alias</replaceab
|
||||
<synopsis>
|
||||
FROM <replaceable>table_reference</replaceable> <replaceable>alias</replaceable>
|
||||
</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.
|
||||
</para>
|
||||
|
||||
@ -1040,13 +1040,32 @@ SELECT a AS value, b + c AS sum FROM ...
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If no output column name is specified using <literal>AS</>, the system assigns a
|
||||
default name. For simple column references, this is the name of the
|
||||
referenced column. For function
|
||||
If no output column name is specified using <literal>AS</>,
|
||||
the system assigns a default column name. For simple column references,
|
||||
this is the name of the referenced column. For function
|
||||
calls, this is the name of the function. For complex expressions,
|
||||
the system will generate a generic name.
|
||||
</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>
|
||||
<para>
|
||||
The naming of output columns here is different from that done in
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -23,7 +23,7 @@ PostgreSQL documentation
|
||||
DELETE FROM [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <replaceable class="parameter">alias</replaceable> ]
|
||||
[ USING <replaceable class="PARAMETER">usinglist</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>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -22,7 +22,7 @@ PostgreSQL documentation
|
||||
<synopsis>
|
||||
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> }
|
||||
[ 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>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -21,7 +21,7 @@ PostgreSQL documentation
|
||||
<refsynopsisdiv>
|
||||
<synopsis>
|
||||
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> [, ...] ]
|
||||
[ WHERE <replaceable class="parameter">condition</replaceable> ]
|
||||
[ GROUP BY <replaceable class="parameter">expression</replaceable> [, ...] ]
|
||||
@ -477,23 +477,45 @@ HAVING <replaceable class="parameter">condition</replaceable>
|
||||
<literal>SELECT</> and <literal>FROM</>) specifies expressions
|
||||
that form the output rows of the <command>SELECT</command>
|
||||
statement. The expressions can (and usually do) refer to columns
|
||||
computed in the <literal>FROM</> clause. Using the clause
|
||||
<literal>AS <replaceable
|
||||
class="parameter">output_name</replaceable></literal>, another
|
||||
name can be specified for an output column. This name is
|
||||
primarily used to label the column for display. It can also 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.
|
||||
computed in the <literal>FROM</> clause.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Just as in a table, every output column of a <command>SELECT</command>
|
||||
has a name. In a simple <command>SELECT</command> this name is just
|
||||
used to label the column for display, but when the <command>SELECT</>
|
||||
is a sub-query of a larger query, the name is seen by the larger query
|
||||
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>
|
||||
Instead of an expression, <literal>*</literal> can be written in
|
||||
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
|
||||
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>
|
||||
</refsect2>
|
||||
|
||||
@ -661,17 +683,17 @@ ORDER BY <replaceable class="parameter">expression</replaceable> [ ASC | DESC |
|
||||
|
||||
<para>
|
||||
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
|
||||
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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is also possible to use arbitrary expressions in the
|
||||
<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:
|
||||
<programlisting>
|
||||
SELECT name FROM distributors ORDER BY code;
|
||||
@ -684,8 +706,8 @@ SELECT name FROM distributors ORDER BY code;
|
||||
|
||||
<para>
|
||||
If an <literal>ORDER BY</> expression is a simple name that
|
||||
matches both a result column name and an input column name,
|
||||
<literal>ORDER BY</> will interpret it as the result column name.
|
||||
matches both an output column name and an input 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
|
||||
make in the same situation. This inconsistency is made to be
|
||||
compatible with the SQL standard.
|
||||
@ -1135,16 +1157,25 @@ SELECT distributors.* WHERE distributors.name = 'Westward';
|
||||
</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</> is just
|
||||
noise and can be omitted without affecting the meaning. The
|
||||
<productname>PostgreSQL</productname> parser requires this key
|
||||
word when renaming output columns because the type extensibility
|
||||
features lead to parsing ambiguities without it.
|
||||
<literal>AS</literal> is optional in <literal>FROM</literal>
|
||||
items, however.
|
||||
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>
|
||||
In <literal>FROM</literal> items, both the standard and
|
||||
<productname>PostgreSQL</productname> allow <literal>AS</> to
|
||||
be omitted before an alias that is an unreserved keyword. But
|
||||
this is impractical for output column names, because of syntactic
|
||||
ambiguities.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
@ -1153,7 +1184,7 @@ SELECT distributors.* WHERE distributors.name = 'Westward';
|
||||
|
||||
<para>
|
||||
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
|
||||
names. <productname>PostgreSQL</productname> extends each of
|
||||
these clauses to allow the other choice as well (but it uses the
|
||||
@ -1161,7 +1192,7 @@ SELECT distributors.* WHERE distributors.name = 'Westward';
|
||||
<productname>PostgreSQL</productname> also allows both clauses to
|
||||
specify arbitrary expressions. Note that names appearing in an
|
||||
expression will always be taken as input-column names, not as
|
||||
result-column names.
|
||||
output-column names.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -21,7 +21,7 @@ PostgreSQL documentation
|
||||
<refsynopsisdiv>
|
||||
<synopsis>
|
||||
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>
|
||||
[ FROM <replaceable class="PARAMETER">from_item</replaceable> [, ...] ]
|
||||
[ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -25,7 +25,7 @@ UPDATE [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <rep
|
||||
( <replaceable class="PARAMETER">column</replaceable> [, ...] ) = ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) } [, ...]
|
||||
[ FROM <replaceable class="PARAMETER">fromlist</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>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $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">
|
||||
<title>SQL</title>
|
||||
@ -853,7 +853,7 @@ A < B + 3.
|
||||
|
||||
<synopsis>
|
||||
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> ]
|
||||
[ FROM <replaceable class="PARAMETER">from_item</replaceable> [, ...] ]
|
||||
[ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -477,6 +477,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
|
||||
%nonassoc BETWEEN
|
||||
%nonassoc IN_P
|
||||
%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 */
|
||||
%nonassoc NOTNULL
|
||||
%nonassoc ISNULL
|
||||
@ -8705,7 +8706,6 @@ target_list:
|
||||
| target_list ',' target_el { $$ = lappend($1, $3); }
|
||||
;
|
||||
|
||||
/* AS is not optional because shift/red conflict with unary ops */
|
||||
target_el: a_expr AS ColLabel
|
||||
{
|
||||
$$ = makeNode(ResTarget);
|
||||
@ -8714,6 +8714,22 @@ target_el: a_expr AS ColLabel
|
||||
$$->val = (Node *)$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
|
||||
{
|
||||
$$ = makeNode(ResTarget);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $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 */
|
||||
%{
|
||||
@ -521,8 +521,9 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu
|
||||
%nonassoc OVERLAPS
|
||||
%nonassoc BETWEEN
|
||||
%nonassoc IN_P
|
||||
%left POSTFIXOP /* dummy for postfix Op rules */
|
||||
%left Op OPERATOR /* multi-character ops and user-defined operators */
|
||||
%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 */
|
||||
%nonassoc NOTNULL
|
||||
%nonassoc ISNULL
|
||||
%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN
|
||||
@ -4695,9 +4696,10 @@ target_list: target_list ',' target_el
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
/* AS is not optional because shift/red conflict with unary ops */
|
||||
target_el: a_expr AS ColLabel
|
||||
{ $$ = cat_str(3, $1, make_str("as"), $3); }
|
||||
| a_expr IDENT
|
||||
{ $$ = cat_str(3, $1, make_str("as"), $2); }
|
||||
| a_expr
|
||||
{ $$ = $1; }
|
||||
| '*'
|
||||
|
@ -2337,9 +2337,9 @@ begin
|
||||
end loop;
|
||||
return 5;
|
||||
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
|
||||
^
|
||||
^
|
||||
QUERY: select I fought the law, the law won
|
||||
CONTEXT: SQL statement in PL/PgSQL function "bad_sql2" near line 3
|
||||
-- a RETURN expression is mandatory, except for void-returning
|
||||
|
Loading…
x
Reference in New Issue
Block a user