Repository: tobymao/sqlglot

Issue:
Support BigQuery `RANGE` type
**Is your feature request related to a problem? Please describe.**

BigQuery added a [`RANGE`](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#range_type) type which takes a type parameter, one of `DATE`, `DATETIME` or `TIMESTAMP`

**Describe the solution you'd like**

Add support for this new type.

**Describe alternatives you've considered**

N/A

**Additional context**

Would like to use this type in sqlmesh models.


Discussion:

Patch:
diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py
index 95f3c01c..de48a8a4 100644
--- a/sqlglot/expressions.py
+++ b/sqlglot/expressions.py
@@ -4123,6 +4123,7 @@ class DataType(Expression):
         NUMRANGE = auto()
         NVARCHAR = auto()
         OBJECT = auto()
+        RANGE = auto()
         ROWVERSION = auto()
         SERIAL = auto()
         SET = auto()
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
index 96df5c01..a9fc38e5 100644
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -269,6 +269,7 @@ class Parser(metaclass=_Parser):
         TokenType.LOWCARDINALITY,
         TokenType.MAP,
         TokenType.NULLABLE,
+        TokenType.RANGE,
         *STRUCT_TYPE_TOKENS,
     }
 


Test patch:
diff --git a/tests/dialects/test_bigquery.py b/tests/dialects/test_bigquery.py
index 2c6a6076..e2adfeab 100644
--- a/tests/dialects/test_bigquery.py
+++ b/tests/dialects/test_bigquery.py
@@ -1962,3 +1962,26 @@ OPTIONS (
                 "duckdb": "WITH Races AS (SELECT '800M' AS race) SELECT race, participant FROM Races AS r CROSS JOIN (SELECT UNNEST([{'name': 'Rudisha', 'laps': [23.4, 26.3, 26.4, 26.1]}], max_depth => 2)) AS participant",
             },
         )
+
+    def test_range_type(self):
+        for type, value in (
+            ("RANGE<DATE>", "'[2020-01-01, 2020-12-31)'"),
+            ("RANGE<DATE>", "'[UNBOUNDED, 2020-12-31)'"),
+            ("RANGE<DATETIME>", "'[2020-01-01 12:00:00, 2020-12-31 12:00:00)'"),
+            ("RANGE<TIMESTAMP>", "'[2020-10-01 12:00:00+08, 2020-12-31 12:00:00+08)'"),
+        ):
+            with self.subTest(f"Testing BigQuery's RANGE<T> type: {type} {value}"):
+                self.validate_identity(f"SELECT {type} {value}", f"SELECT CAST({value} AS {type})")
+
+                self.assertEqual(self.parse_one(type), exp.DataType.build(type, dialect="bigquery"))
+
+        self.validate_identity(
+            "SELECT RANGE(CAST('2022-12-01' AS DATE), CAST('2022-12-31' AS DATE))"
+        )
+        self.validate_identity("SELECT RANGE(NULL, CAST('2022-12-31' AS DATE))")
+        self.validate_identity(
+            "SELECT RANGE(CAST('2022-10-01 14:53:27' AS DATETIME), CAST('2022-10-01 16:00:00' AS DATETIME))"
+        )
+        self.validate_identity(
+            "SELECT RANGE(CAST('2022-10-01 14:53:27 America/Los_Angeles' AS TIMESTAMP), CAST('2022-10-01 16:00:00 America/Los_Angeles' AS TIMESTAMP))"
+        )