Repository: tobymao/sqlglot

Issue:
Regression when parsing complex types with databricks dialect
The following code will throw `sqlglot.errors.ParseError: Expecting >`, even though it is a valid 

```python
import sqlglot

sql = """
CREATE TABLE IF NOT EXISTS db.table (
  a ARRAY<
    STRUCT<
      b INT COMMENT 'nested comment',
      c: MAP<STRING,STRING>
    >
  > COMMENT 'complex type'
)
USING DELTA
"""

sqlglot.parse_one(sql, read="databricks")
```




**Before you file an issue**
- Make sure you specify the "read" dialect eg. `parse_one(sql, read="spark")`
- Make sure you specify the "write" dialect eg. `ast.sql(dialect="duckdb")`
- Check if the issue still exists on main

**Fully reproducible code snippet**
Please include a fully reproducible code snippet or the input sql, dialect, and expected output.

**Official Documentation**
Please include links to official SQL documentation related to your issue.



Discussion:

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -4060,7 +4060,7 @@ def _parse_escape(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expr
             return this
         return self.expression(exp.Escape, this=this, expression=self._parse_string())
 
-    def _parse_interval(self, match_interval: bool = True) -> t.Optional[exp.Interval]:
+    def _parse_interval(self, match_interval: bool = True) -> t.Optional[exp.Add | exp.Interval]:
         index = self._index
 
         if not self._match(TokenType.INTERVAL) and match_interval:
@@ -4106,7 +4106,19 @@ def _parse_interval(self, match_interval: bool = True) -> t.Optional[exp.Interva
                 exp.IntervalSpan, this=unit, expression=self._parse_var(any_token=True, upper=True)
             )
 
-        return self.expression(exp.Interval, this=this, unit=unit)
+        interval = self.expression(exp.Interval, this=this, unit=unit)
+
+        index = self._index
+        self._match(TokenType.PLUS)
+
+        # Convert INTERVAL 'val_1' unit_1 [+] ... [+] 'val_n' unit_n into a sum of intervals
+        if self._match_set((TokenType.STRING, TokenType.NUMBER), advance=False):
+            return self.expression(
+                exp.Add, this=interval, expression=self._parse_interval(match_interval=False)
+            )
+
+        self._retreat(index)
+        return interval
 
     def _parse_bitwise(self) -> t.Optional[exp.Expression]:
         this = self._parse_term()
@@ -4173,38 +4185,32 @@ def _parse_type(
     ) -> 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 True:
-                index = self._index
-                self._match(TokenType.PLUS)
-
-                if not self._match_set((TokenType.STRING, TokenType.NUMBER), advance=False):
-                    self._retreat(index)
-                    break
-
-                interval = self.expression(  # type: ignore
-                    exp.Add, this=interval, expression=self._parse_interval(match_interval=False)
-                )
-
             return interval
 
         index = self._index
         data_type = self._parse_types(check_func=True, allow_identifiers=False)
-        this = self._parse_column()
 
         if data_type:
+            index2 = self._index
+            this = self._parse_primary()
+
             if isinstance(this, exp.Literal):
                 parser = self.TYPE_LITERAL_PARSERS.get(data_type.this)
                 if parser:
                     return parser(self, this, data_type)
+
                 return self.expression(exp.Cast, this=this, to=data_type)
 
-            if not data_type.expressions:
-                self._retreat(index)
-                return self._parse_id_var() if fallback_to_identifier else self._parse_column()
+            if data_type.expressions:
+                self._retreat(index2)
+                return self._parse_column_ops(data_type)
 
-            return self._parse_column_ops(data_type)
+            self._retreat(index)
 
+        if fallback_to_identifier:
+            return self._parse_id_var()
+
+        this = self._parse_column()
         return this and self._parse_column_ops(this)
 
     def _parse_type_size(self) -> t.Optional[exp.DataTypeParam]:


Test patch:
diff --git a/tests/dialects/test_databricks.py b/tests/dialects/test_databricks.py
--- a/tests/dialects/test_databricks.py
+++ b/tests/dialects/test_databricks.py
@@ -9,6 +9,7 @@ class TestDatabricks(Validator):
     def test_databricks(self):
         self.validate_identity("DESCRIBE HISTORY a.b")
         self.validate_identity("DESCRIBE history.tbl")
+        self.validate_identity("CREATE TABLE t (a STRUCT<c: MAP<STRING, STRING>>)")
         self.validate_identity("CREATE TABLE t (c STRUCT<interval: DOUBLE COMMENT 'aaa'>)")
         self.validate_identity("CREATE TABLE my_table TBLPROPERTIES (a.b=15)")
         self.validate_identity("CREATE TABLE my_table TBLPROPERTIES ('a.b'=15)")