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.

Reply via email to