diff --git a/docs/generated/sql/bnf/joined_table.bnf b/docs/generated/sql/bnf/joined_table.bnf index 93e776320852..ae7815f56fd6 100644 --- a/docs/generated/sql/bnf/joined_table.bnf +++ b/docs/generated/sql/bnf/joined_table.bnf @@ -1,6 +1,6 @@ joined_table ::= '(' joined_table ')' - | table_ref 'CROSS' 'JOIN' table_ref + | table_ref 'CROSS' opt_join_hint 'JOIN' table_ref | table_ref ( 'FULL' ( 'OUTER' | ) | 'LEFT' ( 'OUTER' | ) | 'RIGHT' ( 'OUTER' | ) | 'INNER' ) opt_join_hint 'JOIN' table_ref ( 'USING' '(' ( ( name ) ( ( ',' name ) )* ) ')' | 'ON' a_expr ) | table_ref 'JOIN' table_ref ( 'USING' '(' ( ( name ) ( ( ',' name ) )* ) ')' | 'ON' a_expr ) | table_ref 'NATURAL' ( 'FULL' ( 'OUTER' | ) | 'LEFT' ( 'OUTER' | ) | 'RIGHT' ( 'OUTER' | ) | 'INNER' ) opt_join_hint 'JOIN' table_ref diff --git a/docs/generated/sql/bnf/stmt_block.bnf b/docs/generated/sql/bnf/stmt_block.bnf index 4f039ecbde38..62029d41a46b 100644 --- a/docs/generated/sql/bnf/stmt_block.bnf +++ b/docs/generated/sql/bnf/stmt_block.bnf @@ -2024,7 +2024,7 @@ opt_alias_clause ::= joined_table ::= '(' joined_table ')' - | table_ref 'CROSS' 'JOIN' table_ref + | table_ref 'CROSS' opt_join_hint 'JOIN' table_ref | table_ref join_type opt_join_hint 'JOIN' table_ref join_qual | table_ref 'JOIN' table_ref join_qual | table_ref 'NATURAL' join_type opt_join_hint 'JOIN' table_ref @@ -2161,18 +2161,18 @@ char_aliases ::= window_definition ::= window_name 'AS' window_specification -join_type ::= - 'FULL' join_outer - | 'LEFT' join_outer - | 'RIGHT' join_outer - | 'INNER' - opt_join_hint ::= 'HASH' | 'MERGE' | 'LOOKUP' | +join_type ::= + 'FULL' join_outer + | 'LEFT' join_outer + | 'RIGHT' join_outer + | 'INNER' + join_qual ::= 'USING' '(' name_list ')' | 'ON' a_expr diff --git a/pkg/sql/opt/exec/execbuilder/testdata/join b/pkg/sql/opt/exec/execbuilder/testdata/join index 23a42e0564ec..55513211219e 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/join +++ b/pkg/sql/opt/exec/execbuilder/testdata/join @@ -1469,6 +1469,45 @@ render · · · table twocolumn@primary · spans ALL +# Test that we can force a merge join using the NATURAL syntax. +query TTT +EXPLAIN SELECT * FROM onecolumn NATURAL INNER MERGE JOIN twocolumn +---- +render · · + └── join · · + │ type inner + │ equality (x) = (x) + │ mergeJoinOrder +"(x=x)" + ├── sort · · + │ │ order +x + │ └── scan · · + │ table onecolumn@primary + │ spans ALL + └── sort · · + │ order +x + └── scan · · +· table twocolumn@primary +· spans ALL + +# Test that we can force a merge join using the CROSS syntax. +query TTT +EXPLAIN SELECT * FROM onecolumn CROSS MERGE JOIN twocolumn WHERE onecolumn.x = twocolumn.x +---- +join · · + │ type inner + │ equality (x) = (x) + │ mergeJoinOrder +"(x=x)" + ├── sort · · + │ │ order +x + │ └── scan · · + │ table onecolumn@primary + │ spans ALL + └── sort · · + │ order +x + └── scan · · +· table twocolumn@primary +· spans ALL + statement error LOOKUP can only be used with INNER or LEFT joins EXPLAIN SELECT * FROM onecolumn RIGHT LOOKUP JOIN twocolumn USING(x) diff --git a/pkg/sql/parser/parse_test.go b/pkg/sql/parser/parse_test.go index 0b7503d52ec5..3a82e0b26763 100644 --- a/pkg/sql/parser/parse_test.go +++ b/pkg/sql/parser/parse_test.go @@ -938,6 +938,7 @@ func TestParse(t *testing.T) { {`SELECT a FROM t1 INNER JOIN t2 ON a = b`}, {`SELECT a FROM t1 INNER HASH JOIN t2 ON a = b`}, {`SELECT a FROM t1 CROSS JOIN t2`}, + {`SELECT a FROM t1 CROSS LOOKUP JOIN t2`}, {`SELECT a FROM t1 NATURAL JOIN t2`}, {`SELECT a FROM t1 NATURAL INNER MERGE JOIN t2`}, {`SELECT a FROM t1 INNER JOIN t2 USING (a)`}, diff --git a/pkg/sql/parser/sql.y b/pkg/sql/parser/sql.y index 1a1b68eecc05..e7f69e57028f 100644 --- a/pkg/sql/parser/sql.y +++ b/pkg/sql/parser/sql.y @@ -6053,9 +6053,9 @@ joined_table: { $$.val = &tree.ParenTableExpr{Expr: $2.tblExpr()} } -| table_ref CROSS JOIN table_ref +| table_ref CROSS opt_join_hint JOIN table_ref { - $$.val = &tree.JoinTableExpr{JoinType: tree.AstCross, Left: $1.tblExpr(), Right: $4.tblExpr()} + $$.val = &tree.JoinTableExpr{JoinType: tree.AstCross, Left: $1.tblExpr(), Right: $5.tblExpr(), Hint: $3} } | table_ref join_type opt_join_hint JOIN table_ref join_qual { diff --git a/pkg/sql/stats/automatic_stats.go b/pkg/sql/stats/automatic_stats.go index 1341eaec40f5..34654e1f83aa 100644 --- a/pkg/sql/stats/automatic_stats.go +++ b/pkg/sql/stats/automatic_stats.go @@ -408,7 +408,7 @@ func (r *Refresher) maybeRefreshStats( // Log other errors but don't automatically reschedule the refresh, since // that could lead to endless retries. - log.Errorf(ctx, "failed to create statistics on table %d: %v", tableID, err) + log.Warningf(ctx, "failed to create statistics on table %d: %v", tableID, err) return } }