[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
- * | expression [ [ AS ] output_name ] [, ...]
+ [ * | expression [ [ AS ] output_name ] [, ...] ]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY expression [, ...] ]
following query is invalid:
SELECT distributors.* WHERE distributors.name = 'Westward';
-
PostgreSQL releases prior to
+
+
PostgreSQL releases prior to
8.1 would accept queries of this form, and add an implicit entry
to the query's FROM clause for each table
referenced by the query. This is no longer allowed.
+
+
Empty SELECT Lists
+
+ The list of output expressions after SELECT can be
+ empty, producing a zero-column result table.
+ This is not valid syntax according to the SQL standard.
+
PostgreSQL allows it to be consistent with
+ allowing zero-column tables.
+ However, an empty list is not allowed when DISTINCT> is used.
+
+
+
Omitting the AS Key Word
PostgreSQL treats
UNNEST()> the
same as other set-returning functions.
-
- ROWS FROM( ... )> is an extension of the SQL standard.
-
Nonstandard Clauses
- The clause DISTINCT ON is not defined in the
+ DISTINCT ON ( ... ) is an extension of the
SQL standard.
+
+ ROWS FROM( ... )> is an extension of the SQL standard.
+
/* transform RETURNING identically to a SELECT targetlist */
rlist = transformTargetList(pstate, returningList, EXPR_KIND_RETURNING);
+ /*
+ * Complain if the nonempty tlist expanded to nothing (which is possible
+ * if it contains only a star-expansion of a zero-column table). If we
+ * allow this, the parsed Query will look like it didn't have RETURNING,
+ * with results that would probably surprise the user.
+ */
+ if (rlist == NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("RETURNING must have at least one column"),
+ parser_errposition(pstate,
+ exprLocation(linitial(returningList)))));
+
/* mark column origins */
markTargetListOrigins(pstate, rlist);
name_list from_clause from_list opt_array_bounds
qualified_name_list any_name any_name_list
any_operator expr_list attrs
- target_list insert_column_list set_target_list
+ target_list opt_target_list insert_column_list set_target_list
set_clause_list set_clause multiple_set_clause
ctext_expr_list ctext_row def_list indirection opt_indirection
reloption_list group_clause TriggerFuncArgs select_limit
* However, this is not checked by the grammar; parse analysis must check it.
*/
simple_select:
- SELECT opt_distinct target_list
+ SELECT opt_distinct opt_target_list
into_clause from_clause where_clause
group_clause having_clause window_clause
{
*
*****************************************************************************/
+opt_target_list: target_list { $$ = $1; }
+ | /* EMPTY */ { $$ = NIL; }
+ ;
+
target_list:
target_el { $$ = list_make1($1); }
| target_list ',' target_el { $$ = lappend($1, $3); }
true);
}
+ /*
+ * Complain if we found nothing to make DISTINCT. Returning an empty list
+ * would cause the parsed Query to look like it didn't have DISTINCT, with
+ * results that would probably surprise the user. Note: this case is
+ * presently impossible for aggregates because of grammar restrictions,
+ * but we check anyway.
+ */
+ if (result == NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ is_agg ?
+ errmsg("an aggregate with DISTINCT must have at least one argument") :
+ errmsg("SELECT DISTINCT must have at least one column")));
+
return result;
}
true);
}
+ /*
+ * An empty result list is impossible here because of grammar restrictions.
+ */
+ Assert(result != NIL);
+
return result;
}
--
--
-- SELECT
--- missing relation name
+-- this used to be a syntax error, but now we allow an empty target list
select;
-ERROR: syntax error at or near ";"
-LINE 1: select;
- ^
+--
+(1 row)
+
-- no such relation
select * from nonesuch;
ERROR: relation "nonesuch" does not exist
LINE 1: select * from nonesuch;
^
--- missing target list
-select from pg_database;
-ERROR: syntax error at or near "from"
-LINE 1: select from pg_database;
- ^
-- bad name in target list
select nonesuch from pg_database;
ERROR: column "nonesuch" does not exist
LINE 1: select nonesuch from pg_database;
^
+-- empty distinct list isn't OK
+select distinct from pg_database;
+ERROR: SELECT DISTINCT must have at least one column
-- bad attribute name on lhs of operator
select * from pg_database where nonesuch = pg_database.datname;
ERROR: column "nonesuch" does not exist
ERROR: column "nonesuch" does not exist
LINE 1: ...ect * from pg_database where pg_database.datname = nonesuch;
^
--- bad select distinct on syntax, distinct attribute missing
-select distinct on (foobar) from pg_database;
-ERROR: syntax error at or near "from"
-LINE 1: select distinct on (foobar) from pg_database;
- ^
--- bad select distinct on syntax, distinct attribute not in target list
+-- bad attribute name in select distinct on
select distinct on (foobar) * from pg_database;
ERROR: column "foobar" does not exist
LINE 1: select distinct on (foobar) * from pg_database;
--
-- SELECT
--- missing relation name
+-- this used to be a syntax error, but now we allow an empty target list
select;
-- no such relation
select * from nonesuch;
--- missing target list
-select from pg_database;
-- bad name in target list
select nonesuch from pg_database;
+
+-- empty distinct list isn't OK
+select distinct from pg_database;
+
-- bad attribute name on lhs of operator
select * from pg_database where nonesuch = pg_database.datname;
-- bad attribute name on rhs of operator
select * from pg_database where pg_database.datname = nonesuch;
-
--- bad select distinct on syntax, distinct attribute missing
-select distinct on (foobar) from pg_database;
-
-
--- bad select distinct on syntax, distinct attribute not in target list
+-- bad attribute name in select distinct on
select distinct on (foobar) * from pg_database;