Bug #35100 Join syntax documentation incomplete, some inconsistencies and errors
Submitted: 6 Mar 2008 9:58 Modified: 10 Apr 2008 20:11
Reporter: Roland Bouman Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Documentation Severity:S3 (Non-critical)
Version:NA OS:Any
Assigned to: Paul DuBois CPU Architecture:Any

[6 Mar 2008 9:58] Roland Bouman
Description:
The join syntax is explained here:

http://dev.mysql.com/doc/refman/5.1/en/join.html

I think there are 3 issues:

- there is an error in the rule table_factor
- no production for 'subquery in the from clause'
- the rule for join_table is inconsistent in its notation

As a sidenote, there also seems to be a minor inconsistency/error in http://dev.mysql.com/doc/refman/5.1/en/unnamed-views.html 
as compared to
http://dev.mysql.com/doc/refman/5.1/en/subqueries.html
in that sometimes parentheses are sometimes included and sometimes excluded from the subquery production rule.

How to repeat:
http://dev.mysql.com/doc/refman/5.1/en/join.html

Suggested fix:
#1 error in the rule table_factor

The rule now reads:

table_factor:
    tbl_name [[AS] alias] [index_hint_list]
  | ( table_references )
  | { OJ table_reference LEFT OUTER JOIN table_reference
        ON conditional_expr }

I believe the last alternative is wrong. What is "OJ" supposed to mean? This statement for example fails with a syntax error: 

select * from 
OJ actor a LEFT OUTER JOIN film_actor f ON a.actor_id = f.actor_id

(actor a is a valid table_reference - leaving out the alias would also be a valid table_reference, however that would be parsed differently - OJ would be seen as table name, and actor as alias!)

It seems to me the third alternative can be removed without consequence.

#2 subquery in the from clause:

My proposal would be to add the subquery as an alternative to the table_factor rule. It would then read:

table_factor:
    tbl_name [[AS] alias] [index_hint_list]
  | subquery [AS] alias
  | ( table_references )
  | { OJ table_reference LEFT OUTER JOIN table_reference
        ON conditional_expr }

alternatively, the term "derived_table" could be used:

table_factor:
    tbl_name [[AS] alias] [index_hint_list]
  | derived_table
  | ( table_references )
  | { OJ table_reference LEFT OUTER JOIN table_reference
        ON conditional_expr }

where derived_table stands for 

subquery [AS] alias

The documentation should contain a link to 

http://dev.mysql.com/doc/refman/5.1/en/unnamed-views.html

to explain the subquery syntax in this context in more detail.

Sidenote: http://dev.mysql.com/doc/refman/5.1/en/unnamed-views.html uses an inconsistent notation for the subquery syntax. In that page, the 'subquery' is the part that appears within the parentheses, whereas in http://dev.mysql.com/doc/refman/5.1/en/subqueries.html, the subquery includes the parentheses. Personally, I think the rule should be:

subquery := '(' select-expression ')'

or 

subquery := '(' query-expression ')'

#3 inconsistent notation for the rule join_table:

right now, the rule reads:

join_table:
    table_reference [INNER | CROSS] JOIN table_factor [join_condition]
  | table_reference STRAIGHT_JOIN table_factor
  | table_reference STRAIGHT_JOIN table_factor ON condition
  | table_reference LEFT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [LEFT [OUTER]] JOIN table_factor
  | table_reference RIGHT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [RIGHT [OUTER]] JOIN table_factor

The inconsistency is observed in the first three alternatives. The first alternative uses an optional join_condition, whereas the next two could be written using a similar construct like so:

  | table_reference STRAIGHT_JOIN table_factor [ON condition]

Personally I would prefer it if the last four alternatives would be written like so:

  | table_reference LEFT|RIGHT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [LEFT|RIGHT [OUTER]] JOIN table_factor

In conclusion, the entire rule would then become:

join_table:
    table_reference [INNER | CROSS] JOIN table_factor [join_condition]
  | table_reference STRAIGHT_JOIN table_factor [ON condition]
  | table_reference LEFT|RIGHT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [LEFT|RIGHT [OUTER]] JOIN table_factor

which I personally find easier to understand.
[10 Apr 2008 20:11] Paul DuBois
Thank you for your bug report. This issue has been addressed in the documentation. The updated documentation will appear on our website shortly, and will be included in the next release of the relevant products.

1) The OJ production is correct. It's noted later in the section that the curly brackets and OJ are literal tokens. I have added an example to illustrate the syntax better.

2) table_subquery (subquery in the FROM clause) has been added as a valid production for table_factor.

3) Productions for LEFT and RIGHT join have been combined where possible.
[17 Jun 2008 23:50] Brian Schneider
where is conditional_expr defined?  i can not find it in any of the documentation.
[18 Jun 2008 17:26] Paul DuBois
Brian,

"
The ON conditional is any conditional expression of the form that can be used in a WHERE clause. Generally, you should use the ON clause for conditions that specify how to join tables, and the WHERE clause to restrict which rows you want in the result set.
"

http://dev.mysql.com/doc/refman/5.1/en/join.html

I will modify this to specifically say "conditional_expr" in the paragraph.