Repository: tobymao/sqlglot

Issue:
INTERVAL '5' hours '30' minutes not working.
Not able to parse databricks query which contains `INTERVAL x hours y minutes`.

getting this error.

`sqlglot.errors.ParseError: Expecting ).`

Discussion:

Patch:
diff --git a/sqlglot/dialects/snowflake.py b/sqlglot/dialects/snowflake.py
index f88f3eb1..6ca8e9de 100644
--- a/sqlglot/dialects/snowflake.py
+++ b/sqlglot/dialects/snowflake.py
@@ -663,7 +663,9 @@ class Snowflake(Dialect):
             "MINUS": TokenType.EXCEPT,
             "NCHAR VARYING": TokenType.VARCHAR,
             "PUT": TokenType.COMMAND,
+            "REMOVE": TokenType.COMMAND,
             "RENAME": TokenType.REPLACE,
+            "RM": TokenType.COMMAND,
             "SAMPLE": TokenType.TABLE_SAMPLE,
             "SQL_DOUBLE": TokenType.DOUBLE,
             "SQL_VARCHAR": TokenType.VARCHAR,
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
index fd4317e9..50e365e5 100644
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -3449,10 +3449,10 @@ class Parser(metaclass=_Parser):
             return this
         return self.expression(exp.Escape, this=this, expression=self._parse_string())
 
-    def _parse_interval(self) -> t.Optional[exp.Interval]:
+    def _parse_interval(self, match_interval: bool = True) -> t.Optional[exp.Interval]:
         index = self._index
 
-        if not self._match(TokenType.INTERVAL):
+        if not self._match(TokenType.INTERVAL) and match_interval:
             return None
 
         if self._match(TokenType.STRING, advance=False):
@@ -3545,6 +3545,12 @@ class Parser(metaclass=_Parser):
     def _parse_type(self, parse_interval: bool = True) -> t.Optional[exp.Expression]:
         interval = parse_interval and self._parse_interval()
         if interval:
+            # Convert INTERVAL 'val_1' unit_1 ... 'val_n' unit_n into a sum of intervals
+            while self._match_set((TokenType.STRING, TokenType.NUMBER), advance=False):
+                interval = self.expression(  # type: ignore
+                    exp.Add, this=interval, expression=self._parse_interval(match_interval=False)
+                )
+
             return interval
 
         index = self._index


Test patch:
diff --git a/tests/dialects/test_snowflake.py b/tests/dialects/test_snowflake.py
index 1f365bea..5dd81cdc 100644
--- a/tests/dialects/test_snowflake.py
+++ b/tests/dialects/test_snowflake.py
@@ -39,6 +39,8 @@ WHERE
   )""",
         )
 
+        self.validate_identity("RM @parquet_stage")
+        self.validate_identity("REMOVE @parquet_stage")
         self.validate_identity("SELECT TIMESTAMP_FROM_PARTS(d, t)")
         self.validate_identity("SELECT GET_PATH(v, 'attr[0].name') FROM vartab")
         self.validate_identity("SELECT TO_ARRAY(CAST(x AS ARRAY))")
diff --git a/tests/dialects/test_spark.py b/tests/dialects/test_spark.py
index 43d0577f..ef7fd656 100644
--- a/tests/dialects/test_spark.py
+++ b/tests/dialects/test_spark.py
@@ -254,6 +254,14 @@ TBLPROPERTIES (
         self.validate_identity("TRIM(LEADING 'SL' FROM 'SSparkSQLS')")
         self.validate_identity("TRIM(TRAILING 'SL' FROM 'SSparkSQLS')")
         self.validate_identity("SPLIT(str, pattern, lim)")
+        self.validate_identity(
+            "SELECT INTERVAL '5' HOURS '30' MINUTES '5' SECONDS '6' MILLISECONDS '7' MICROSECONDS",
+            "SELECT INTERVAL '5' HOURS + INTERVAL '30' MINUTES + INTERVAL '5' SECONDS + INTERVAL '6' MILLISECONDS + INTERVAL '7' MICROSECONDS",
+        )
+        self.validate_identity(
+            "SELECT INTERVAL 5 HOURS 30 MINUTES 5 SECONDS 6 MILLISECONDS 7 MICROSECONDS",
+            "SELECT INTERVAL '5' HOURS + INTERVAL '30' MINUTES + INTERVAL '5' SECONDS + INTERVAL '6' MILLISECONDS + INTERVAL '7' MICROSECONDS",
+        )
         self.validate_identity(
             "SELECT REGEXP_REPLACE('100-200', r'([^0-9])', '')",
             "SELECT REGEXP_REPLACE('100-200', '([^0-9])', '')",