On Sun, Mar 18, 2018 at 02:28:26PM -0700, David G. Johnston wrote: > As a first step we could do something like: > > basic_select_statement is: > > > SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] > [ * | expression [ [ AS ] output_name ] [, ...] ] > [ FROM from_item [, ...] ] > [ WHERE condition ] > [ GROUP BY grouping_element [, ...] ] > [ HAVING condition [, ...] ] > [ WINDOW window_name AS ( window_definition ) [, ...] ] > > > full_select_statement is basic_select_statement with the following possible > additional clauses tacked onto the end: > > > [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST > | > LAST } ] [, ...] ] > [ LIMIT { count | ALL } ] > [ OFFSET start [ ROW | ROWS ] ] > [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ] > [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name > [, > ...] ] [ NOWAIT | SKIP LOCKED ] [...] ] > > and that's still not right because ORDER BY et al can't be attached to a > select_stmt that's the argument of a set operation, so really we'd need > a couple of levels of nonterminals before we get down to the basic > "SELECT expression FROM ..." part. Nor has the use of parentheses been > mentioned yet. > > > Then we can define the set clauses in terms of basic_select_stmt and > parentheses-surrounded full_select_stmt. The result of the set clause is > itself > a type of basic_select_statement which can be made full by adding one or more > of the additional clauses, including ORDER BY.
Based on this discussion, I have developed the attached patch which tries to clarify the behavior without adding complexity. If this is applied, should it be backpatched as a fix? -- Bruce Momjian <br...@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + As you are, so once was I. As I am, so you will be. + + Ancient Roman grave inscription +
diff --git a/doc/src/sgml/ref/select.sgml b/doc/src/sgml/ref/select.sgml new file mode 100644 index b5d3d3a..2c6c49c *** a/doc/src/sgml/ref/select.sgml --- b/doc/src/sgml/ref/select.sgml *************** SELECT [ ALL | DISTINCT [ ON ( <replacea *** 40,46 **** [ GROUP BY <replaceable class="parameter">grouping_element</replaceable> [, ...] ] [ HAVING <replaceable class="parameter">condition</replaceable> [, ...] ] [ WINDOW <replaceable class="parameter">window_name</replaceable> AS ( <replaceable class="parameter">window_definition</replaceable> ) [, ...] ] ! [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] <replaceable class="parameter">select</replaceable> ] [ ORDER BY <replaceable class="parameter">expression</replaceable> [ ASC | DESC | USING <replaceable class="parameter">operator</replaceable> ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { <replaceable class="parameter">count</replaceable> | ALL } ] [ OFFSET <replaceable class="parameter">start</replaceable> [ ROW | ROWS ] ] --- 40,46 ---- [ GROUP BY <replaceable class="parameter">grouping_element</replaceable> [, ...] ] [ HAVING <replaceable class="parameter">condition</replaceable> [, ...] ] [ WINDOW <replaceable class="parameter">window_name</replaceable> AS ( <replaceable class="parameter">window_definition</replaceable> ) [, ...] ] ! [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] <replaceable class="parameter">limited_select</replaceable> ] [ ORDER BY <replaceable class="parameter">expression</replaceable> [ ASC | DESC | USING <replaceable class="parameter">operator</replaceable> ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { <replaceable class="parameter">count</replaceable> | ALL } ] [ OFFSET <replaceable class="parameter">start</replaceable> [ ROW | ROWS ] ] *************** TABLE [ ONLY ] <replaceable class="param *** 152,157 **** --- 152,166 ---- <listitem> <para> + <replaceable class="parameter">limited_select</replaceable> is one or + more additional <command>SELECT</command> queries using only clauses + listed above this item. Clauses after this item can only be appended + to the last <command>SELECT</command>, unless parentheses are used. + </para> + </listitem> + + <listitem> + <para> Using the operators <literal>UNION</literal>, <literal>INTERSECT</literal>, and <literal>EXCEPT</literal>, the output of more than one <command>SELECT</command> statement can *************** TABLE [ ONLY ] <replaceable class="param *** 251,260 **** <command>SELECT</command> subquery to reference itself by name. Such a subquery must have the form <synopsis> ! <replaceable class="parameter">non_recursive_term</replaceable> UNION [ ALL | DISTINCT ] <replaceable class="parameter">recursive_term</replaceable> </synopsis> where the recursive self-reference must appear on the right-hand ! side of the <literal>UNION</literal>. Only one recursive self-reference is permitted per query. Recursive data-modifying statements are not supported, but you can use the results of a recursive <command>SELECT</command> query in --- 260,271 ---- <command>SELECT</command> subquery to reference itself by name. Such a subquery must have the form <synopsis> ! <replaceable class="parameter">non_recursive_term</replaceable> { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] <replaceable class="parameter">recursive_term</replaceable> </synopsis> where the recursive self-reference must appear on the right-hand ! side of ! <literal>UNION</literal>/<literal>INTERSECT</literal>/<literal>EXCEPT</literal>. ! Only one recursive self-reference is permitted per query. Recursive data-modifying statements are not supported, but you can use the results of a recursive <command>SELECT</command> query in *************** SELECT DISTINCT ON (location) location, *** 1129,1144 **** <para> The <literal>UNION</literal> clause has this general form: <synopsis> ! <replaceable class="parameter">select_statement</replaceable> UNION [ ALL | DISTINCT ] <replaceable class="parameter">select_statement</replaceable> ! </synopsis><replaceable class="parameter">select_statement</replaceable> is any <command>SELECT</command> statement without an <literal>ORDER BY</literal>, <literal>LIMIT</literal>, <literal>FOR NO KEY UPDATE</literal>, <literal>FOR UPDATE</literal>, <literal>FOR SHARE</literal>, or <literal>FOR KEY SHARE</literal> clause. ! (<literal>ORDER BY</literal> and <literal>LIMIT</literal> can be attached to a ! subexpression if it is enclosed in parentheses. Without ! parentheses, these clauses will be taken to apply to the result of ! the <literal>UNION</literal>, not to its right-hand input ! expression.) </para> <para> --- 1140,1154 ---- <para> The <literal>UNION</literal> clause has this general form: <synopsis> ! [ <replaceable class="parameter">limited_select</replaceable> UNION [ ALL | DISTINCT ] [ ... ] <replaceable class="parameter">select</replaceable> ! </synopsis><replaceable class="parameter">limited_select</replaceable> is any <command>SELECT</command> statement without an <literal>ORDER BY</literal>, <literal>LIMIT</literal>, <literal>FOR NO KEY UPDATE</literal>, <literal>FOR UPDATE</literal>, <literal>FOR SHARE</literal>, or <literal>FOR KEY SHARE</literal> clause. ! (<literal>ORDER BY</literal> and <literal>LIMIT</literal> can be ! attached if it is enclosed in parentheses.) The final <replaceable ! class="parameter">select</replaceable> can contain the clauses listed ! above and those are applied to the result of the <literal>UNION</literal>. </para> <para> *************** SELECT DISTINCT ON (location) location, *** 1182,1189 **** <para> The <literal>INTERSECT</literal> clause has this general form: <synopsis> ! <replaceable class="parameter">select_statement</replaceable> INTERSECT [ ALL | DISTINCT ] <replaceable class="parameter">select_statement</replaceable> ! </synopsis><replaceable class="parameter">select_statement</replaceable> is any <command>SELECT</command> statement without an <literal>ORDER BY</literal>, <literal>LIMIT</literal>, <literal>FOR NO KEY UPDATE</literal>, <literal>FOR UPDATE</literal>, <literal>FOR SHARE</literal>, or <literal>FOR KEY SHARE</literal> clause. --- 1192,1199 ---- <para> The <literal>INTERSECT</literal> clause has this general form: <synopsis> ! <replaceable class="parameter">limited_select</replaceable> INTERSECT [ ALL | DISTINCT ] [ ... ] <replaceable class="parameter">select_statement</replaceable> ! </synopsis><replaceable class="parameter">limited_select</replaceable> is any <command>SELECT</command> statement without an <literal>ORDER BY</literal>, <literal>LIMIT</literal>, <literal>FOR NO KEY UPDATE</literal>, <literal>FOR UPDATE</literal>, <literal>FOR SHARE</literal>, or <literal>FOR KEY SHARE</literal> clause. *************** SELECT DISTINCT ON (location) location, *** 1230,1237 **** <para> The <literal>EXCEPT</literal> clause has this general form: <synopsis> ! <replaceable class="parameter">select_statement</replaceable> EXCEPT [ ALL | DISTINCT ] <replaceable class="parameter">select_statement</replaceable> ! </synopsis><replaceable class="parameter">select_statement</replaceable> is any <command>SELECT</command> statement without an <literal>ORDER BY</literal>, <literal>LIMIT</literal>, <literal>FOR NO KEY UPDATE</literal>, <literal>FOR UPDATE</literal>, <literal>FOR SHARE</literal>, or <literal>FOR KEY SHARE</literal> clause. --- 1240,1247 ---- <para> The <literal>EXCEPT</literal> clause has this general form: <synopsis> ! <replaceable class="parameter">limited_select</replaceable> EXCEPT [ ALL | DISTINCT ] [ ... ] <replaceable class="parameter">select_statement</replaceable> ! </synopsis><replaceable class="parameter">limited_select</replaceable> is any <command>SELECT</command> statement without an <literal>ORDER BY</literal>, <literal>LIMIT</literal>, <literal>FOR NO KEY UPDATE</literal>, <literal>FOR UPDATE</literal>, <literal>FOR SHARE</literal>, or <literal>FOR KEY SHARE</literal> clause.