Repository: tobymao/sqlglot

Issue:
[Postgres] Parser does not support operators inside extract() function
Example (valid sql):
```
select extract(week from current_date + 2);
```

Result:
```
ParseError: Expecting ). Line 1, Col: 39.
  select extract(week from current_date + 2);

Invalid expression / Unexpected token. Line 1, Col: 42.
  select extract(week from current_date + 2);
```

The addition operator can be substituted for other operators, yielding the same exception.

Discussion:

Patch:
diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py
index 8b2fc28c..1e66147b 100644
--- a/sqlglot/expressions.py
+++ b/sqlglot/expressions.py
@@ -885,10 +885,6 @@ class Reference(Expression):
     arg_types = {"this": True, "expressions": True}
 
 
-class Table(Expression):
-    arg_types = {"this": True, "db": False, "catalog": False}
-
-
 class Tuple(Expression):
     arg_types = {"expressions": False}
 
@@ -998,6 +994,10 @@ QUERY_MODIFIERS = {
 }
 
 
+class Table(Expression):
+    arg_types = {"this": True, "db": False, "catalog": False, **QUERY_MODIFIERS}
+
+
 class Union(Subqueryable, Expression):
     arg_types = {
         "with": False,
diff --git a/sqlglot/generator.py b/sqlglot/generator.py
index d893f155..e36bf531 100644
--- a/sqlglot/generator.py
+++ b/sqlglot/generator.py
@@ -531,7 +531,7 @@ class Generator:
         return f"{self.sql(expression, 'this')} {self.sql(expression, 'expression')}"
 
     def table_sql(self, expression):
-        return ".".join(
+        table = ".".join(
             part
             for part in [
                 self.sql(expression, "catalog"),
@@ -541,6 +541,8 @@ class Generator:
             if part
         )
 
+        return f"{table}{self.query_modifiers(expression)}"
+
     def tablesample_sql(self, expression):
         if self.alias_post_tablesample and isinstance(expression.this, exp.Alias):
             this = self.sql(expression.this, "this")
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
index cc3b4bd8..2df99526 100644
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -1032,7 +1032,7 @@ class Parser:
         return self.expression(exp.Subquery, this=this, alias=self._parse_table_alias())
 
     def _parse_query_modifiers(self, this):
-        if not isinstance(this, (exp.Subquery, exp.Subqueryable)):
+        if not isinstance(this, (exp.Subquery, exp.Subqueryable, exp.Table)):
             return
 
         for key, parser in self.QUERY_MODIFIER_PARSERS.items():
@@ -1904,7 +1904,7 @@ class Parser:
         if not self._match(TokenType.FROM):
             self.raise_error("Expected FROM after EXTRACT", self._prev)
 
-        return self.expression(exp.Extract, this=this, expression=self._parse_type())
+        return self.expression(exp.Extract, this=this, expression=self._parse_bitwise())
 
     def _parse_cast(self, strict):
         this = self._parse_conjunction()


Test patch:
diff --git a/tests/dialects/test_dialect.py b/tests/dialects/test_dialect.py
index 10babba9..aa49843b 100644
--- a/tests/dialects/test_dialect.py
+++ b/tests/dialects/test_dialect.py
@@ -631,6 +631,33 @@ class TestDialect(Validator):
             },
         )
 
+    # https://dev.mysql.com/doc/refman/8.0/en/join.html
+    # https://www.postgresql.org/docs/current/queries-table-expressions.html
+    def test_joined_tables(self):
+        self.validate_identity("SELECT * FROM (tbl1 LEFT JOIN tbl2 ON 1 = 1)")
+        self.validate_identity("SELECT * FROM (tbl1 JOIN tbl2 JOIN tbl3)")
+        self.validate_identity(
+            "SELECT * FROM (tbl1 JOIN (tbl2 JOIN tbl3) ON bla = foo)"
+        )
+        self.validate_identity(
+            "SELECT * FROM (tbl1 JOIN LATERAL (SELECT * FROM bla) AS tbl)"
+        )
+
+        self.validate_all(
+            "SELECT * FROM (tbl1 LEFT JOIN tbl2 ON 1 = 1)",
+            write={
+                "postgres": "SELECT * FROM (tbl1 LEFT JOIN tbl2 ON 1 = 1)",
+                "mysql": "SELECT * FROM (tbl1 LEFT JOIN tbl2 ON 1 = 1)",
+            },
+        )
+        self.validate_all(
+            "SELECT * FROM (tbl1 JOIN LATERAL (SELECT * FROM bla) AS tbl)",
+            write={
+                "postgres": "SELECT * FROM (tbl1 JOIN LATERAL (SELECT * FROM bla) AS tbl)",
+                "mysql": "SELECT * FROM (tbl1 JOIN LATERAL (SELECT * FROM bla) AS tbl)",
+            },
+        )
+
     def test_lateral_subquery(self):
         self.validate_identity(
             "SELECT art FROM tbl1 INNER JOIN LATERAL (SELECT art FROM tbl2) AS tbl2 ON tbl1.art = tbl2.art"
diff --git a/tests/test_transpile.py b/tests/test_transpile.py
index 28bcc7a7..6ef33777 100644
--- a/tests/test_transpile.py
+++ b/tests/test_transpile.py
@@ -108,6 +108,13 @@ class TestTranspile(unittest.TestCase):
             "extract(month from '2021-01-31'::timestamp without time zone)",
             "EXTRACT(month FROM CAST('2021-01-31' AS TIMESTAMP))",
         )
+        self.validate(
+            "extract(week from current_date + 2)", "EXTRACT(week FROM CURRENT_DATE + 2)"
+        )
+        self.validate(
+            "EXTRACT(minute FROM datetime1 - datetime2)",
+            "EXTRACT(minute FROM datetime1 - datetime2)",
+        )
 
     def test_if(self):
         self.validate(