Repository: tobymao/sqlglot

Issue:
Snowflake to_array implemented incorrectly 
The docs for snowflake implementation of [to_array](https://docs.snowflake.com/en/sql-reference/functions/to_array) state 

> If the input is an ARRAY, or VARIANT containing an array value, the result is unchanged.
> For NULL or a JSON null input, returns NULL.
> For any other value, the result is a single-element array containing this value.

As we can see below, the input as an array, the result is an array of arrays which is not unchanged. 
```
>>> parse_one("select to_array(['test']) from test;", dialect="snowflake").sql(pretty=True)
"SELECT\n  ARRAY(ARRAY('test'))\nFROM test"
```

```
sqlglot==20.2.0
```




Discussion:
I raised this PR https://github.com/tobymao/sqlglot/pull/2696
> I raised this PR #2696

See https://github.com/tobymao/sqlglot/pull/2696#issuecomment-1860263568

Resolving patch:
diff --git a/sqlglot/dialects/snowflake.py b/sqlglot/dialects/snowflake.py
--- a/sqlglot/dialects/snowflake.py
+++ b/sqlglot/dialects/snowflake.py
@@ -33,6 +33,21 @@ def _check_int(s: str) -> bool:
     return s.isdigit()
 
 
+def _parse_to_array(args: t.List) -> exp.Expression:
+    arg = seq_get(args, 0)
+    if isinstance(arg, exp.Expression):
+        from sqlglot.optimizer.annotate_types import annotate_types
+
+        # https://docs.snowflake.com/en/sql-reference/functions/to_array
+        arg = annotate_types(arg)
+        if arg.is_type(exp.DataType.Type.ARRAY):
+            return arg
+        if arg.is_type(exp.DataType.Type.VARIANT):
+            return exp.Anonymous(this="TO_ARRAY", expressions=[arg])
+
+    return exp.Array.from_arg_list(args)
+
+
 # from https://docs.snowflake.com/en/sql-reference/functions/to_timestamp.html
 def _parse_to_timestamp(args: t.List) -> t.Union[exp.StrToTime, exp.UnixToTime, exp.TimeStrToTime]:
     if len(args) == 2:
@@ -293,7 +308,7 @@ class Parser(parser.Parser):
             "SQUARE": lambda args: exp.Pow(this=seq_get(args, 0), expression=exp.Literal.number(2)),
             "TIMEDIFF": _parse_datediff,
             "TIMESTAMPDIFF": _parse_datediff,
-            "TO_ARRAY": exp.Array.from_arg_list,
+            "TO_ARRAY": _parse_to_array,
             "TO_TIMESTAMP": _parse_to_timestamp,
             "TO_VARCHAR": exp.ToChar.from_arg_list,
             "ZEROIFNULL": _zeroifnull_to_if,


Test patch:
diff --git a/tests/dialects/test_snowflake.py b/tests/dialects/test_snowflake.py
--- a/tests/dialects/test_snowflake.py
+++ b/tests/dialects/test_snowflake.py
@@ -127,11 +127,45 @@ def test_snowflake(self):
             "SELECT TO_TIMESTAMP(x) FROM t",
             "SELECT CAST(x AS TIMESTAMPNTZ) FROM t",
         )
+        self.validate_identity(
+            "CAST(x AS BYTEINT)",
+            "CAST(x AS INT)",
+        )
+        self.validate_identity(
+            "CAST(x AS CHAR VARYING)",
+            "CAST(x AS VARCHAR)",
+        )
+        self.validate_identity(
+            "CAST(x AS CHARACTER VARYING)",
+            "CAST(x AS VARCHAR)",
+        )
+        self.validate_identity(
+            "CAST(x AS NCHAR VARYING)",
+            "CAST(x AS VARCHAR)",
+        )
+        self.validate_identity(
+            "SELECT TO_ARRAY(x::ARRAY)",
+            "SELECT CAST(x AS ARRAY)",
+        )
+        self.validate_identity(
+            "SELECT TO_ARRAY(['test']::VARIANT)",
+            "SELECT TO_ARRAY(CAST(['test'] AS VARIANT))",
+        )
 
-        self.validate_all("CAST(x AS BYTEINT)", write={"snowflake": "CAST(x AS INT)"})
-        self.validate_all("CAST(x AS CHAR VARYING)", write={"snowflake": "CAST(x AS VARCHAR)"})
-        self.validate_all("CAST(x AS CHARACTER VARYING)", write={"snowflake": "CAST(x AS VARCHAR)"})
-        self.validate_all("CAST(x AS NCHAR VARYING)", write={"snowflake": "CAST(x AS VARCHAR)"})
+        self.validate_all(
+            "SELECT TO_ARRAY(['test'])",
+            write={
+                "snowflake": "SELECT ['test']",
+                "spark": "SELECT ARRAY('test')",
+            },
+        )
+        self.validate_all(
+            "SELECT TO_ARRAY(['test'])",
+            write={
+                "snowflake": "SELECT ['test']",
+                "spark": "SELECT ARRAY('test')",
+            },
+        )
         self.validate_all(
             # We need to qualify the columns in this query because "value" would be ambiguous
             'WITH t(x, "value") AS (SELECT [1, 2, 3], 1) SELECT IFF(_u.pos = _u_2.pos_2, _u_2."value", NULL) AS "value" FROM t, TABLE(FLATTEN(INPUT => ARRAY_GENERATE_RANGE(0, (GREATEST(ARRAY_SIZE(t.x)) - 1) + 1))) AS _u(seq, key, path, index, pos, this) CROSS JOIN TABLE(FLATTEN(INPUT => t.x)) AS _u_2(seq, key, path, pos_2, "value", this) WHERE _u.pos = _u_2.pos_2 OR (_u.pos > (ARRAY_SIZE(t.x) - 1) AND _u_2.pos_2 = (ARRAY_SIZE(t.x) - 1))',