On Sat, Aug 13, 2022 at 10:21:26PM -0400, Tom Lane wrote:
> Bruce Momjian <br...@momjian.us> writes:
> > Hi, I agree we should show the more modern JOIN sytax.  However, this is
> > just an example, so one example should be sufficient.  I went with the
> > first one in the attached patch.
> 
> You should not remove the CROSS JOIN mention at l. 604, first because
> the references to it just below would become odd, and second because
> then it's not explained anywhere on the page.  Perhaps you could
> put back a definition of CROSS JOIN just below the entry for NATURAL,
> but you'll still have to do something with the references at l. 614,
> 628, 632.

Good point.  I restrutured the docs to move CROSS JOIN to a separate
section like NATURAL and adjusted the text, patch attached.

> Also, doesn't "[ AS join_using_alias ]" apply to NATURAL and CROSS
> joins?  You've left that out of the syntax summary.

Uh, I only see it for USING in gram.y:

        /* JOIN qualification clauses
         * Possibilities are:
         *  USING ( column list ) [ AS alias ]
         *                        allows only unqualified column names,
         *                        which must match between tables.
         *  ON expr allows more general qualifications.
         *
         * We return USING as a two-element List (the first item being a 
sub-List
         * of the common column names, and the second either an Alias item or 
NULL).
         * An ON-expr will not be a List, so it can be told apart that way.
         */
        
        join_qual: USING '(' name_list ')' opt_alias_clause_for_join_using
                        {
                            $$ = (Node *) list_make2($3, $5);
                        }
                    | ON a_expr
                        {
                            $$ = $2;
                        }
                ;

        ...

        /*
         * The alias clause after JOIN ... USING only accepts the AS ColId 
spelling,
         * per SQL standard.  (The grammar could parse the other variants, but 
they
         * don't seem to be useful, and it might lead to parser problems in the
         * future.)
         */
        opt_alias_clause_for_join_using:
                    AS ColId
                        {
                            $$ = makeNode(Alias);
                            $$->aliasname = $2;
                            /* the column name list will be inserted later */
                        }
                    | /*EMPTY*/                             { $$ = NULL; }
                ;

which is only used in:

        | table_ref join_type JOIN table_ref join_qual
        | table_ref JOIN table_ref join_qual

I have updated my private build:

        https://momjian.us/tmp/pgsql/sql-select.html

-- 
  Bruce Momjian  <br...@momjian.us>        https://momjian.us
  EDB                                      https://enterprisedb.com

  Indecision is a decision.  Inaction is an action.  Mark Batterson

diff --git a/doc/src/sgml/ref/select.sgml b/doc/src/sgml/ref/select.sgml
new file mode 100644
index 410c80e..1f9538f
*** a/doc/src/sgml/ref/select.sgml
--- b/doc/src/sgml/ref/select.sgml
*************** SELECT [ ALL | DISTINCT [ ON ( <replacea
*** 59,65 ****
      [ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
      [ LATERAL ] ROWS FROM( <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] ) ] [, ...] )
                  [ WITH ORDINALITY ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
!     <replaceable class="parameter">from_item</replaceable> [ NATURAL ] <replaceable class="parameter">join_type</replaceable> <replaceable class="parameter">from_item</replaceable> [ ON <replaceable class="parameter">join_condition</replaceable> | USING ( <replaceable class="parameter">join_column</replaceable> [, ...] ) [ AS <replaceable class="parameter">join_using_alias</replaceable> ] ]
  
  <phrase>and <replaceable class="parameter">grouping_element</replaceable> can be one of:</phrase>
  
--- 59,67 ----
      [ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
      [ LATERAL ] ROWS FROM( <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] ) ] [, ...] )
                  [ WITH ORDINALITY ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
!     <replaceable class="parameter">from_item</replaceable> <replaceable class="parameter">join_type</replaceable> <replaceable class="parameter">from_item</replaceable> { ON <replaceable class="parameter">join_condition</replaceable> | USING ( <replaceable class="parameter">join_column</replaceable> [, ...] ) [ AS <replaceable class="parameter">join_using_alias</replaceable> ] }
!     <replaceable class="parameter">from_item</replaceable> NATURAL <replaceable class="parameter">join_type</replaceable> <replaceable class="parameter">from_item</replaceable>
!     <replaceable class="parameter">from_item</replaceable> CROSS JOIN <replaceable class="parameter">from_item</replaceable>
  
  <phrase>and <replaceable class="parameter">grouping_element</replaceable> can be one of:</phrase>
  
*************** TABLE [ ONLY ] <replaceable class="param
*** 600,618 ****
           <listitem>
            <para><literal>FULL [ OUTER ] JOIN</literal></para>
           </listitem>
-          <listitem>
-           <para><literal>CROSS JOIN</literal></para>
-          </listitem>
          </itemizedlist>
  
          For the <literal>INNER</literal> and <literal>OUTER</literal> join types, a
          join condition must be specified, namely exactly one of
!         <literal>NATURAL</literal>, <literal>ON <replaceable
!         class="parameter">join_condition</replaceable></literal>, or
          <literal>USING (<replaceable
!         class="parameter">join_column</replaceable> [, ...])</literal>.
!         See below for the meaning.  For <literal>CROSS JOIN</literal>,
!         none of these clauses can appear.
         </para>
  
         <para>
--- 602,616 ----
           <listitem>
            <para><literal>FULL [ OUTER ] JOIN</literal></para>
           </listitem>
          </itemizedlist>
  
          For the <literal>INNER</literal> and <literal>OUTER</literal> join types, a
          join condition must be specified, namely exactly one of
!         <literal>ON <replaceable
!         class="parameter">join_condition</replaceable></literal>,
          <literal>USING (<replaceable
!         class="parameter">join_column</replaceable> [, ...])</literal>,
!         or <literal>NATURAL</literal>.  See below for the meaning.
         </para>
  
         <para>
*************** TABLE [ ONLY ] <replaceable class="param
*** 623,639 ****
          In the absence of parentheses, <literal>JOIN</literal>s nest
          left-to-right.  In any case <literal>JOIN</literal> binds more
          tightly than the commas separating <literal>FROM</literal>-list items.
!        </para>
! 
!        <para><literal>CROSS JOIN</literal> and <literal>INNER JOIN</literal>
!         produce a simple Cartesian product, the same result as you get from
!         listing the two tables at the top level of <literal>FROM</literal>,
!         but restricted by the join condition (if any).
!         <literal>CROSS JOIN</literal> is equivalent to <literal>INNER JOIN ON
!         (TRUE)</literal>, that is, no rows are removed by qualification.
!         These join types are just a notational convenience, since they
!         do nothing you couldn't do with plain <literal>FROM</literal> and
!         <literal>WHERE</literal>.
         </para>
  
         <para><literal>LEFT OUTER JOIN</literal> returns all rows in the qualified
--- 621,629 ----
          In the absence of parentheses, <literal>JOIN</literal>s nest
          left-to-right.  In any case <literal>JOIN</literal> binds more
          tightly than the commas separating <literal>FROM</literal>-list items.
!         All the <literal>JOIN</literal> options are just a notational
!         convenience, since they do nothing you couldn't do with plain
!         <literal>FROM</literal> and <literal>WHERE</literal>.
         </para>
  
         <para><literal>LEFT OUTER JOIN</literal> returns all rows in the qualified
*************** TABLE [ ONLY ] <replaceable class="param
*** 715,720 ****
--- 705,723 ----
       </varlistentry>
  
       <varlistentry>
+       <term><literal>CROSS JOIN</literal></term>
+       <listitem>
+        <para>
+         <literal>CROSS JOIN</literal> is equivalent to <literal>INNER JOIN ON
+         (TRUE)</literal>, that is, no rows are removed by qualification.
+         They produce a simple Cartesian product, the same result as you get from
+         listing the two tables at the top level of <literal>FROM</literal>,
+         but restricted by the join condition (if any).
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
        <term><literal>LATERAL</literal></term>
        <listitem>
         <para>
*************** SELECT * FROM <replaceable class="parame
*** 1754,1761 ****
  
  <programlisting>
  SELECT f.title, f.did, d.name, f.date_prod, f.kind
!     FROM distributors d, films f
!     WHERE f.did = d.did
  
         title       | did |     name     | date_prod  |   kind
  -------------------+-----+--------------+------------+----------
--- 1757,1763 ----
  
  <programlisting>
  SELECT f.title, f.did, d.name, f.date_prod, f.kind
!     FROM distributors d JOIN films f USING (did);
  
         title       | did |     name     | date_prod  |   kind
  -------------------+-----+--------------+------------+----------

Reply via email to