Repository: tobymao/sqlglot

Issue:
dblink domain throw ParseError for Oracle dialect
If you try to parse the statement below it returns an Invalid expression / unexpected token error
`sql_query = """  SELECT * FROM table_name@dblink_name.database_link_domain;""" 
parsed = parse_one(sql_query , read='oracle')`

**Retrieved Error**
![image](https://user-images.githubusercontent.com/30730327/236172628-2b9398a6-8c5f-4eae-89f5-5e78f3137f87.png)

Adding DB domain link is optional but some times is needed to specify the complete service name. The syntax is as above
More info here: [Oracle Docs](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CREATE-DATABASE-LINK.html#GUID-D966642A-B19E-449D-9968-1121AF06D793)

Discussion:

Patch:
diff --git a/sqlglot/dialects/oracle.py b/sqlglot/dialects/oracle.py
index fb4ec426..9100099b 100644
--- a/sqlglot/dialects/oracle.py
+++ b/sqlglot/dialects/oracle.py
@@ -165,6 +165,8 @@ class Oracle(Dialect):
             return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}"
 
     class Tokenizer(tokens.Tokenizer):
+        VAR_SINGLE_TOKENS = {"@"}
+
         KEYWORDS = {
             **tokens.Tokenizer.KEYWORDS,
             "(+)": TokenType.JOIN_MARKER,
diff --git a/sqlglot/dialects/spark2.py b/sqlglot/dialects/spark2.py
index 84da5f59..6056940e 100644
--- a/sqlglot/dialects/spark2.py
+++ b/sqlglot/dialects/spark2.py
@@ -26,6 +26,10 @@ def _map_sql(self: Hive.Generator, expression: exp.Map) -> str:
     return f"MAP_FROM_ARRAYS({keys}, {values})"
 
 
+def _parse_as_cast(to_type: str) -> t.Callable[[t.Sequence], exp.Expression]:
+    return lambda args: exp.Cast(this=seq_get(args, 0), to=exp.DataType.build(to_type))
+
+
 def _str_to_date(self: Hive.Generator, expression: exp.StrToDate) -> str:
     this = self.sql(expression, "this")
     time_format = self.format_time(expression)
@@ -77,11 +81,7 @@ class Spark2(Hive):
                 length=seq_get(args, 1),
             ),
             "APPROX_PERCENTILE": exp.ApproxQuantile.from_arg_list,
-            "BOOLEAN": lambda args: exp.Cast(
-                this=seq_get(args, 0), to=exp.DataType.build("boolean")
-            ),
             "IIF": exp.If.from_arg_list,
-            "INT": lambda args: exp.Cast(this=seq_get(args, 0), to=exp.DataType.build("int")),
             "AGGREGATE": exp.Reduce.from_arg_list,
             "DAYOFWEEK": lambda args: exp.DayOfWeek(
                 this=exp.TsOrDsToDate(this=seq_get(args, 0)),
@@ -100,11 +100,13 @@ class Spark2(Hive):
                 this=seq_get(args, 1),
                 unit=exp.var(seq_get(args, 0)),
             ),
-            "STRING": lambda args: exp.Cast(this=seq_get(args, 0), to=exp.DataType.build("string")),
             "TRUNC": lambda args: exp.DateTrunc(unit=seq_get(args, 1), this=seq_get(args, 0)),
-            "TIMESTAMP": lambda args: exp.Cast(
-                this=seq_get(args, 0), to=exp.DataType.build("timestamp")
-            ),
+            "BOOLEAN": _parse_as_cast("boolean"),
+            "DOUBLE": _parse_as_cast("double"),
+            "FLOAT": _parse_as_cast("float"),
+            "INT": _parse_as_cast("int"),
+            "STRING": _parse_as_cast("string"),
+            "TIMESTAMP": _parse_as_cast("timestamp"),
         }
 
         FUNCTION_PARSERS = {


Test patch:
diff --git a/tests/dialects/test_oracle.py b/tests/dialects/test_oracle.py
index dd297d6b..0d707b73 100644
--- a/tests/dialects/test_oracle.py
+++ b/tests/dialects/test_oracle.py
@@ -5,6 +5,7 @@ class TestOracle(Validator):
     dialect = "oracle"
 
     def test_oracle(self):
+        self.validate_identity("SELECT * FROM table_name@dblink_name.database_link_domain")
         self.validate_identity("SELECT * FROM V$SESSION")
         self.validate_identity(
             "SELECT MIN(column_name) KEEP (DENSE_RANK FIRST ORDER BY column_name DESC) FROM table_name"
diff --git a/tests/dialects/test_spark.py b/tests/dialects/test_spark.py
index a5fc043a..31dfb37d 100644
--- a/tests/dialects/test_spark.py
+++ b/tests/dialects/test_spark.py
@@ -225,20 +225,15 @@ TBLPROPERTIES (
                 "trino": "SELECT DATE_DIFF('MONTH', CAST(SUBSTR(CAST('2020-01-01' AS VARCHAR), 1, 10) AS DATE), CAST(SUBSTR(CAST('2020-03-05' AS VARCHAR), 1, 10) AS DATE))",
             },
         )
-        self.validate_all(
-            "BOOLEAN(x)",
-            write={
-                "": "CAST(x AS BOOLEAN)",
-                "spark": "CAST(x AS BOOLEAN)",
-            },
-        )
-        self.validate_all(
-            "INT(x)",
-            write={
-                "": "CAST(x AS INT)",
-                "spark": "CAST(x AS INT)",
-            },
-        )
+
+        for data_type in ("BOOLEAN", "DATE", "DOUBLE", "FLOAT", "INT", "TIMESTAMP"):
+            self.validate_all(
+                f"{data_type}(x)",
+                write={
+                    "": f"CAST(x AS {data_type})",
+                    "spark": f"CAST(x AS {data_type})",
+                },
+            )
         self.validate_all(
             "STRING(x)",
             write={
@@ -246,20 +241,7 @@ TBLPROPERTIES (
                 "spark": "CAST(x AS STRING)",
             },
         )
-        self.validate_all(
-            "DATE(x)",
-            write={
-                "": "CAST(x AS DATE)",
-                "spark": "CAST(x AS DATE)",
-            },
-        )
-        self.validate_all(
-            "TIMESTAMP(x)",
-            write={
-                "": "CAST(x AS TIMESTAMP)",
-                "spark": "CAST(x AS TIMESTAMP)",
-            },
-        )
+
         self.validate_all(
             "CAST(x AS TIMESTAMP)", read={"trino": "CAST(x AS TIMESTAMP(6) WITH TIME ZONE)"}
         )