Skip to content

Commit 3f50d42

Browse files
committed
add support to nested join_without parentheses snowflake
1 parent 776b10a commit 3f50d42

2 files changed

Lines changed: 114 additions & 2 deletions

File tree

src/parser/mod.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11695,6 +11695,11 @@ impl<'a> Parser<'a> {
1169511695
// Note that for keywords to be properly handled here, they need to be
1169611696
// added to `RESERVED_FOR_TABLE_ALIAS`, otherwise they may be parsed as
1169711697
// a table alias.
11698+
let joins = self.parse_joins()?;
11699+
Ok(TableWithJoins { relation, joins })
11700+
}
11701+
11702+
fn parse_joins(&mut self) -> Result<Vec<Join>, ParserError> {
1169811703
let mut joins = vec![];
1169911704
loop {
1170011705
let global = self.parse_keyword(Keyword::GLOBAL);
@@ -11823,7 +11828,16 @@ impl<'a> Parser<'a> {
1182311828
}
1182411829
_ => break,
1182511830
};
11826-
let relation = self.parse_table_factor()?;
11831+
let mut relation = self.parse_table_factor()?;
11832+
11833+
if self.is_next_token_a_join() {
11834+
let joins = self.parse_joins()?;
11835+
relation = TableFactor::NestedJoin {
11836+
table_with_joins: Box::new(TableWithJoins { relation, joins }),
11837+
alias: None,
11838+
};
11839+
}
11840+
1182711841
let join_constraint = self.parse_join_constraint(natural)?;
1182811842
Join {
1182911843
relation,
@@ -11833,7 +11847,21 @@ impl<'a> Parser<'a> {
1183311847
};
1183411848
joins.push(join);
1183511849
}
11836-
Ok(TableWithJoins { relation, joins })
11850+
Ok(joins)
11851+
}
11852+
11853+
fn is_next_token_a_join(&self) -> bool {
11854+
matches!(
11855+
self.peek_token().token,
11856+
Token::Word(Word {
11857+
keyword: Keyword::JOIN
11858+
| Keyword::INNER
11859+
| Keyword::LEFT
11860+
| Keyword::RIGHT
11861+
| Keyword::FULL,
11862+
..
11863+
})
11864+
)
1183711865
}
1183811866

1183911867
/// A table name or a parenthesized subquery, followed by optional `[AS] alias`

tests/sqlparser_snowflake.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3516,3 +3516,87 @@ fn test_alter_session_followed_by_statement() {
35163516
_ => panic!("Unexpected statements: {:?}", stmts),
35173517
}
35183518
}
3519+
3520+
#[test]
3521+
fn test_nested_join_without_parentheses() {
3522+
let query = "SELECT DISTINCT p.product_id FROM orders AS o INNER JOIN customers AS c INNER JOIN products AS p ON p.customer_id = c.customer_id ON c.order_id = o.order_id";
3523+
assert_eq!(
3524+
only(
3525+
snowflake()
3526+
.verified_only_select_with_canonical(query, "")
3527+
.from
3528+
)
3529+
.joins,
3530+
vec![Join {
3531+
relation: TableFactor::NestedJoin {
3532+
table_with_joins: Box::new(TableWithJoins {
3533+
relation: TableFactor::Table {
3534+
name: ObjectName::from(vec![Ident::new("customers".to_string())]),
3535+
alias: Some(TableAlias {
3536+
name: Ident {
3537+
value: "c".to_string(),
3538+
quote_style: None,
3539+
span: Span::empty(),
3540+
},
3541+
columns: vec![],
3542+
}),
3543+
args: None,
3544+
with_hints: vec![],
3545+
version: None,
3546+
partitions: vec![],
3547+
with_ordinality: false,
3548+
json_path: None,
3549+
sample: None,
3550+
index_hints: vec![],
3551+
},
3552+
joins: vec![Join {
3553+
relation: TableFactor::Table {
3554+
name: ObjectName::from(vec![Ident::new("products".to_string())]),
3555+
alias: Some(TableAlias {
3556+
name: Ident {
3557+
value: "p".to_string(),
3558+
quote_style: None,
3559+
span: Span::empty(),
3560+
},
3561+
columns: vec![],
3562+
}),
3563+
args: None,
3564+
with_hints: vec![],
3565+
version: None,
3566+
partitions: vec![],
3567+
with_ordinality: false,
3568+
json_path: None,
3569+
sample: None,
3570+
index_hints: vec![],
3571+
},
3572+
global: false,
3573+
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
3574+
left: Box::new(Expr::CompoundIdentifier(vec![
3575+
Ident::new("p".to_string()),
3576+
Ident::new("customer_id".to_string())
3577+
])),
3578+
op: BinaryOperator::Eq,
3579+
right: Box::new(Expr::CompoundIdentifier(vec![
3580+
Ident::new("c".to_string()),
3581+
Ident::new("customer_id".to_string())
3582+
])),
3583+
})),
3584+
}]
3585+
}),
3586+
alias: None
3587+
},
3588+
global: false,
3589+
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
3590+
left: Box::new(Expr::CompoundIdentifier(vec![
3591+
Ident::new("c".to_string()),
3592+
Ident::new("order_id".to_string())
3593+
])),
3594+
op: BinaryOperator::Eq,
3595+
right: Box::new(Expr::CompoundIdentifier(vec![
3596+
Ident::new("o".to_string()),
3597+
Ident::new("order_id".to_string())
3598+
])),
3599+
}))
3600+
}],
3601+
);
3602+
}

0 commit comments

Comments
 (0)