Skip to content

Commit

Permalink
fix: > 1 nested joins closes #3231
Browse files Browse the repository at this point in the history
  • Loading branch information
tobymao committed Mar 28, 2024
1 parent b097da5 commit bf94ce3
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 10 deletions.
4 changes: 3 additions & 1 deletion sqlglot/generator.py
Expand Up @@ -1636,7 +1636,9 @@ def table_sql(self, expression: exp.Table, sep: str = " AS ") -> str:
hints = f" {hints}" if hints and self.TABLE_HINTS else ""
pivots = self.expressions(expression, key="pivots", sep=" ", flat=True)
pivots = f" {pivots}" if pivots else ""
joins = self.expressions(expression, key="joins", sep="", skip_first=True)
joins = self.indent(
self.expressions(expression, key="joins", sep="", flat=True), skip_first=True
)
laterals = self.expressions(expression, key="laterals", sep="")

file_format = self.sql(expression, "format")
Expand Down
21 changes: 13 additions & 8 deletions sqlglot/parser.py
Expand Up @@ -2658,7 +2658,7 @@ def _parse_query_modifiers(
self, this: t.Optional[exp.Expression]
) -> t.Optional[exp.Expression]:
if isinstance(this, (exp.Query, exp.Table)):
for join in iter(self._parse_join, None):
for join in self._parse_joins():
this.append("joins", join)
for lateral in iter(self._parse_lateral, None):
this.append("laterals", lateral)
Expand Down Expand Up @@ -2903,19 +2903,21 @@ def _parse_join(
kwargs["on"] = self._parse_conjunction()
elif self._match(TokenType.USING):
kwargs["using"] = self._parse_wrapped_id_vars()
elif not (kind and kind.token_type == TokenType.CROSS):
elif not isinstance(kwargs["this"], exp.Unnest) and not (
kind and kind.token_type == TokenType.CROSS
):
index = self._index
join = self._parse_join()
joins: t.Optional[list] = list(self._parse_joins())

if join and self._match(TokenType.ON):
if joins and self._match(TokenType.ON):
kwargs["on"] = self._parse_conjunction()
elif join and self._match(TokenType.USING):
elif joins and self._match(TokenType.USING):
kwargs["using"] = self._parse_wrapped_id_vars()
else:
join = None
joins = None
self._retreat(index)

kwargs["this"].set("joins", [join] if join else None)
kwargs["this"].set("joins", joins if joins else None)

comments = [c for token in (method, side, kind) if token for c in token.comments]
return self.expression(exp.Join, comments=comments, **kwargs)
Expand Down Expand Up @@ -3152,7 +3154,7 @@ def _parse_table(
this = table_sample

if joins:
for join in iter(self._parse_join, None):
for join in self._parse_joins():
this.append("joins", join)

if self._match_pair(TokenType.WITH, TokenType.ORDINALITY):
Expand Down Expand Up @@ -3301,6 +3303,9 @@ def _parse_table_sample(self, as_modifier: bool = False) -> t.Optional[exp.Table
def _parse_pivots(self) -> t.Optional[t.List[exp.Pivot]]:
return list(iter(self._parse_pivot, None)) or None

def _parse_joins(self) -> t.Iterator[exp.Join]:
return iter(self._parse_join, None)

# https://duckdb.org/docs/sql/statements/pivot
def _parse_simplified_pivot(self) -> exp.Pivot:
def _parse_on() -> t.Optional[exp.Expression]:
Expand Down
11 changes: 11 additions & 0 deletions tests/fixtures/pretty.sql
Expand Up @@ -384,3 +384,14 @@ JOIN b
CROSS JOIN d
JOIN e
ON d.id = e.id;

SELECT * FROM a JOIN b JOIN c USING (e) JOIN d USING (f) USING (g);
SELECT
*
FROM a
JOIN b
JOIN c
USING (e)
JOIN d
USING (f)
USING (g);
2 changes: 1 addition & 1 deletion tests/test_transpile.py
Expand Up @@ -518,9 +518,9 @@ def test_comments(self):
*
FROM x
INNER JOIN y
/* inner join z */
LEFT JOIN z
USING (id)
/* inner join z */
USING (id)""",
pretty=True,
)
Expand Down

0 comments on commit bf94ce3

Please sign in to comment.