Skip to content

Commit

Permalink
on condition requirement for join
Browse files Browse the repository at this point in the history
  • Loading branch information
demetribu committed Nov 25, 2024
1 parent 0fb2ef3 commit a3244ea
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 5 deletions.
23 changes: 21 additions & 2 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10102,10 +10102,30 @@ impl<'a> Parser<'a> {
};
let relation = self.parse_table_factor()?;
let join_constraint = self.parse_join_constraint(natural)?;
let join_operator = join_operator_type(join_constraint);

let requires_constraint = match join_operator {
JoinOperator::Inner(JoinConstraint::None)
| JoinOperator::LeftOuter(JoinConstraint::None)
| JoinOperator::RightOuter(JoinConstraint::None)
| JoinOperator::FullOuter(JoinConstraint::None)
| JoinOperator::LeftSemi(JoinConstraint::None)
| JoinOperator::RightSemi(JoinConstraint::None)
| JoinOperator::LeftAnti(JoinConstraint::None)
| JoinOperator::RightAnti(JoinConstraint::None)
| JoinOperator::Semi(JoinConstraint::None)
| JoinOperator::Anti(JoinConstraint::None) => !natural,
_ => false,
};

if requires_constraint {
self.expected("ON, or USING after JOIN", self.peek_token())?
}

Join {
relation,
global,
join_operator: join_operator_type(join_constraint),
join_operator,
}
};
joins.push(join);
Expand Down Expand Up @@ -10914,7 +10934,6 @@ impl<'a> Parser<'a> {
Ok(JoinConstraint::Using(columns))
} else {
Ok(JoinConstraint::None)
//self.expected("ON, or USING after JOIN", self.peek_token())
}
}

Expand Down
48 changes: 46 additions & 2 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7444,7 +7444,7 @@ fn lateral_derived() {

#[test]
fn lateral_function() {
let sql = "SELECT * FROM customer LEFT JOIN LATERAL generate_series(1, customer.id)";
let sql = "SELECT * FROM customer CROSS JOIN LATERAL generate_series(1, customer.id)";
let actual_select_only = verified_only_select(sql);
let expected = Select {
distinct: None,
Expand Down Expand Up @@ -7485,7 +7485,7 @@ fn lateral_function() {
alias: None,
},
global: false,
join_operator: JoinOperator::LeftOuter(JoinConstraint::None),
join_operator: JoinOperator::CrossJoin,
}],
}],
lateral_views: vec![],
Expand Down Expand Up @@ -12198,3 +12198,47 @@ fn parse_create_table_select() {
);
}
}

#[test]
fn parse_no_condition_join_strategy() {
let dialects = all_dialects_where(|d| d.supports_create_table_select());

let join_types = vec![
"JOIN",
"INNER JOIN",
"LEFT JOIN",
"LEFT OUTER JOIN",
"RIGHT JOIN",
"RIGHT OUTER JOIN",
"FULL JOIN",
"FULL OUTER JOIN",
"CROSS JOIN",
"NATURAL JOIN",
"LEFT SEMI JOIN",
"RIGHT SEMI JOIN",
"LEFT ANTI JOIN",
"RIGHT ANTI JOIN",
"SEMI JOIN",
"ANTI JOIN",
];

for join in join_types {
let sql = format!(
"SELECT * FROM (SELECT 1 AS id, 'Foo' AS name) AS l {} (SELECT 1 AS id, 'Bar' AS name) AS r",
join
);
let result = dialects.parse_sql_statements(&sql);
if join.starts_with("CROSS") || join.starts_with("NATURAL") {
// CROSS JOIN and NATURAL JOIN don't require ON or USING clauses
assert!(result.is_ok());
} else {
// Other joins require ON or USING clauses
assert_eq!(
result.unwrap_err(),
ParserError::ParserError(
"Expected: ON, or USING after JOIN, found: EOF".to_string()
)
);
}
}
}
2 changes: 1 addition & 1 deletion tests/sqlparser_hive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ fn test_distribute_by() {

#[test]
fn no_join_condition() {
let join = "SELECT a, b FROM db.table_name JOIN a";
let join = "SELECT a, b FROM db.table_name CROSS JOIN a";
hive().verified_stmt(join);
}

Expand Down

0 comments on commit a3244ea

Please sign in to comment.