Repository: tobymao/sqlglot

Issue:
Hive Dialect for "GROUPING SETS" error
when parsing 'grouping sets', the column cannot use table alias, and any other functions. Or, there is a ParseError.

A good "GROUPING SETS' case
![image](https://user-images.githubusercontent.com/34465781/215730424-1940fb93-35ef-4f1e-929d-0f9e757edfbd.png)

After adding table alias
![image](https://user-images.githubusercontent.com/34465781/215730550-bfc5c93e-e82b-4afa-8979-3012b5aa1c58.png)
![image](https://user-images.githubusercontent.com/34465781/215730590-0fb11429-c25b-408d-9250-dd803a6f7b92.png)

Or, add some function
![image](https://user-images.githubusercontent.com/34465781/215730908-80e9db5a-e215-4510-b3a3-a035bd3b54a1.png)
![image](https://user-images.githubusercontent.com/34465781/215730922-342bfa9a-15ed-4a57-adf8-70d8bdaa5d28.png)


Discussion:

Patch:
diff --git a/.gitignore b/.gitignore
index 0297caf2..b5be650e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -135,3 +135,4 @@ dmypy.json
 .vscode
 
 .DS_STORE
+metastore_db
diff --git a/sqlglot/dialects/spark.py b/sqlglot/dialects/spark.py
index 42d34c20..fc711abb 100644
--- a/sqlglot/dialects/spark.py
+++ b/sqlglot/dialects/spark.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
 
 from sqlglot import exp, parser
-from sqlglot.dialects.dialect import create_with_partitions_sql, rename_func
+from sqlglot.dialects.dialect import create_with_partitions_sql, rename_func, trim_sql
 from sqlglot.dialects.hive import Hive
 from sqlglot.helper import seq_get
 
@@ -122,6 +122,7 @@ class Spark(Hive):
             exp.Reduce: rename_func("AGGREGATE"),
             exp.StructKwarg: lambda self, e: f"{self.sql(e, 'this')}: {self.sql(e, 'expression')}",
             exp.TimestampTrunc: lambda self, e: f"DATE_TRUNC({self.sql(e, 'unit')}, {self.sql(e, 'this')})",
+            exp.Trim: trim_sql,
             exp.VariancePop: rename_func("VAR_POP"),
             exp.DateFromParts: rename_func("MAKE_DATE"),
             exp.LogicalOr: rename_func("BOOL_OR"),
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
index f06a9c8f..723e733c 100644
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -1880,11 +1880,11 @@ class Parser(metaclass=_Parser):
 
     def _parse_grouping_set(self) -> t.Optional[exp.Expression]:
         if self._match(TokenType.L_PAREN):
-            grouping_set = self._parse_csv(self._parse_id_var)
+            grouping_set = self._parse_csv(self._parse_column)
             self._match_r_paren()
             return self.expression(exp.Tuple, expressions=grouping_set)
 
-        return self._parse_id_var()
+        return self._parse_column()
 
     def _parse_having(self, skip_having_token: bool = False) -> t.Optional[exp.Expression]:
         if not skip_having_token and not self._match(TokenType.HAVING):
@@ -2825,7 +2825,7 @@ class Parser(metaclass=_Parser):
             position = self._prev.text.upper()
 
         expression = self._parse_term()
-        if self._match(TokenType.FROM):
+        if self._match_set((TokenType.FROM, TokenType.COMMA)):
             this = self._parse_term()
         else:
             this = expression


Test patch:
diff --git a/tests/dialects/test_hive.py b/tests/dialects/test_hive.py
index d485593f..54d56e45 100644
--- a/tests/dialects/test_hive.py
+++ b/tests/dialects/test_hive.py
@@ -338,6 +338,15 @@ class TestHive(Validator):
         )
 
     def test_hive(self):
+        self.validate_identity(
+            "SELECT a, b, SUM(c) FROM tabl AS t GROUP BY a, b GROUPING SETS ((a, b), a)"
+        )
+        self.validate_identity(
+            "SELECT a, b, SUM(c) FROM tabl AS t GROUP BY a, b GROUPING SETS ((t.a, b), a)"
+        )
+        self.validate_identity(
+            "SELECT a, b, SUM(c) FROM tabl AS t GROUP BY a, FOO(b) GROUPING SETS ((a, FOO(b)), a)"
+        )
         self.validate_all(
             "SELECT A.1a AS b FROM test_a AS A",
             write={
@@ -615,3 +624,20 @@ class TestHive(Validator):
                 "spark": "SELECT * FROM x TABLESAMPLE(1) AS foo",
             },
         )
+        self.validate_all(
+            "SELECT * FROM x TABLESAMPLE(1) AS foo",
+            read={
+                "presto": "SELECT * FROM x AS foo TABLESAMPLE(1)",
+            },
+            write={
+                "presto": "SELECT * FROM x AS foo TABLESAMPLE(1)",
+                "hive": "SELECT * FROM x TABLESAMPLE(1) AS foo",
+                "spark": "SELECT * FROM x TABLESAMPLE(1) AS foo",
+            },
+        )
+        self.validate_all(
+            "SELECT a, SUM(c) FROM t GROUP BY a, DATE_FORMAT(b, 'yyyy') GROUPING SETS ((a, DATE_FORMAT(b, 'yyyy')), a)",
+            write={
+                "hive": "SELECT a, SUM(c) FROM t GROUP BY a, DATE_FORMAT(CAST(b AS TIMESTAMP), 'yyyy') GROUPING SETS ((a, DATE_FORMAT(CAST(b AS TIMESTAMP), 'yyyy')), a)",
+            },
+        )
diff --git a/tests/dialects/test_postgres.py b/tests/dialects/test_postgres.py
index ee01df54..90b07f8c 100644
--- a/tests/dialects/test_postgres.py
+++ b/tests/dialects/test_postgres.py
@@ -57,6 +57,7 @@ class TestPostgres(Validator):
 
     def test_postgres(self):
         self.validate_identity("SELECT ARRAY[1, 2, 3]")
+        self.validate_identity("SELECT ARRAY(SELECT 1)")
         self.validate_identity("SELECT ARRAY_LENGTH(ARRAY[1, 2, 3], 1)")
         self.validate_identity("STRING_AGG(x, y)")
         self.validate_identity("STRING_AGG(x, ',' ORDER BY y)")
@@ -88,6 +89,14 @@ class TestPostgres(Validator):
         self.validate_identity("SELECT e'\\xDEADBEEF'")
         self.validate_identity("SELECT CAST(e'\\176' AS BYTEA)")
         self.validate_identity("""SELECT * FROM JSON_TO_RECORDSET(z) AS y("rank" INT)""")
+        self.validate_identity(
+            "SELECT SUM(x) OVER a, SUM(y) OVER b FROM c WINDOW a AS (PARTITION BY d), b AS (PARTITION BY e)"
+        )
+        self.validate_identity(
+            "CREATE TABLE A (LIKE B INCLUDING CONSTRAINT INCLUDING COMPRESSION EXCLUDING COMMENTS)"
+        )
+        self.validate_identity("x ~ 'y'")
+        self.validate_identity("x ~* 'y'")
 
         self.validate_all(
             "END WORK AND NO CHAIN",
@@ -118,10 +127,6 @@ class TestPostgres(Validator):
             "SELECT to_timestamp(123)::time without time zone",
             write={"postgres": "SELECT CAST(TO_TIMESTAMP(123) AS TIME)"},
         )
-
-        self.validate_identity(
-            "CREATE TABLE A (LIKE B INCLUDING CONSTRAINT INCLUDING COMPRESSION EXCLUDING COMMENTS)"
-        )
         self.validate_all(
             "SELECT SUM(x) OVER (PARTITION BY a ORDER BY d ROWS 1 PRECEDING)",
             write={
@@ -283,9 +288,6 @@ class TestPostgres(Validator):
             "UPDATE MYTABLE T1 SET T1.COL = 13",
             write={"postgres": "UPDATE MYTABLE AS T1 SET T1.COL = 13"},
         )
-
-        self.validate_identity("x ~ 'y'")
-        self.validate_identity("x ~* 'y'")
         self.validate_all(
             "x !~ 'y'",
             write={"postgres": "NOT x ~ 'y'"},
@@ -319,15 +321,16 @@ class TestPostgres(Validator):
             "'x' 'y' 'z'",
             write={"postgres": "CONCAT('x', 'y', 'z')"},
         )
-        self.validate_identity("SELECT ARRAY(SELECT 1)")
-
         self.validate_all(
             "x::cstring",
             write={"postgres": "CAST(x AS CSTRING)"},
         )
-
-        self.validate_identity(
-            "SELECT SUM(x) OVER a, SUM(y) OVER b FROM c WINDOW a AS (PARTITION BY d), b AS (PARTITION BY e)"
+        self.validate_all(
+            "TRIM(BOTH 'as' FROM 'as string as')",
+            write={
+                "postgres": "TRIM(BOTH 'as' FROM 'as string as')",
+                "spark": "TRIM(BOTH 'as' FROM 'as string as')",
+            },
         )
 
     def test_bool_or(self):
diff --git a/tests/dialects/test_spark.py b/tests/dialects/test_spark.py
index 294caa32..02d43aaa 100644
--- a/tests/dialects/test_spark.py
+++ b/tests/dialects/test_spark.py
@@ -208,6 +208,13 @@ TBLPROPERTIES (
 
     def test_spark(self):
         self.validate_identity("SELECT UNIX_TIMESTAMP()")
+        self.validate_identity("TRIM('    SparkSQL   ')")
+        self.validate_identity("TRIM(BOTH 'SL' FROM 'SSparkSQLS')")
+        self.validate_identity("TRIM(LEADING 'SL' FROM 'SSparkSQLS')")
+        self.validate_identity("TRIM(TRAILING 'SL' FROM 'SSparkSQLS')")
+        self.validate_all(
+            "TRIM('SL', 'SSparkSQLS')", write={"spark": "TRIM('SL' FROM 'SSparkSQLS')"}
+        )
         self.validate_all(
             "ARRAY_SORT(x, (left, right) -> -1)",
             write={