internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: tobymao/sqlglot

Issue:
Trino to SparkSQL transpilation error: DATE_DIFF('seconds', x, y)
I'm seeing an error in transpilation in a complex query: 

`date_diff('second', x, y)` transpiling to `date_diff(TO_DATE(x), TO_DATE(y))`

In a simple example, it transpiles to:
```
>>> sqlglot.transpile("select date_diff('seconds', x, y)", read='trino', write='spark')
['SELECT DATEDIFF(y, x)']
```

... but `date_diff('seconds', x, y)` returns the difference in seconds between x and y, whereas DATEDIFF(x,y) returns the difference in days.  A sparksql equivalent might be `unix_timestamp(y) - unix_timestamp(x)`.


Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/hive.py b/sqlglot/dialects/hive.py
--- a/sqlglot/dialects/hive.py
+++ b/sqlglot/dialects/hive.py
@@ -34,6 +34,13 @@
     "DAY": ("DATE_ADD", 1),
 }
 
+TIME_DIFF_FACTOR = {
+    "MILLISECOND": " * 1000",
+    "SECOND": "",
+    "MINUTE": " / 60",
+    "HOUR": " / 3600",
+}
+
 DIFF_MONTH_SWITCH = ("YEAR", "QUARTER", "MONTH")
 
 
@@ -51,6 +58,14 @@ def _add_date_sql(self: generator.Generator, expression: exp.DateAdd) -> str:
 
 def _date_diff_sql(self: generator.Generator, expression: exp.DateDiff) -> str:
     unit = expression.text("unit").upper()
+
+    factor = TIME_DIFF_FACTOR.get(unit)
+    if factor is not None:
+        left = self.sql(expression, "this")
+        right = self.sql(expression, "expression")
+        sec_diff = f"UNIX_TIMESTAMP({left}) - UNIX_TIMESTAMP({right})"
+        return f"({sec_diff}){factor}" if factor else sec_diff
+
     sql_func = "MONTHS_BETWEEN" if unit in DIFF_MONTH_SWITCH else "DATEDIFF"
     _, multiplier = DATE_DELTA_INTERVAL.get(unit, ("", 1))
     multiplier_sql = f" / {multiplier}" if multiplier > 1 else ""


Test patch:
diff --git a/tests/dialects/test_hive.py b/tests/dialects/test_hive.py
--- a/tests/dialects/test_hive.py
+++ b/tests/dialects/test_hive.py
@@ -246,6 +246,30 @@ def test_regex(self):
         )
 
     def test_time(self):
+        self.validate_all(
+            "(UNIX_TIMESTAMP(y) - UNIX_TIMESTAMP(x)) * 1000",
+            read={
+                "presto": "DATE_DIFF('millisecond', x, y)",
+            },
+        )
+        self.validate_all(
+            "UNIX_TIMESTAMP(y) - UNIX_TIMESTAMP(x)",
+            read={
+                "presto": "DATE_DIFF('second', x, y)",
+            },
+        )
+        self.validate_all(
+            "(UNIX_TIMESTAMP(y) - UNIX_TIMESTAMP(x)) / 60",
+            read={
+                "presto": "DATE_DIFF('minute', x, y)",
+            },
+        )
+        self.validate_all(
+            "(UNIX_TIMESTAMP(y) - UNIX_TIMESTAMP(x)) / 3600",
+            read={
+                "presto": "DATE_DIFF('hour', x, y)",
+            },
+        )
         self.validate_all(
             "DATEDIFF(a, b)",
             write={
Repository: tobymao/sqlglot

Issue:
Tilde operator fails to parse with the duckdb dialect
Fails for duckdb, but works for postgres:

```
In [1]: import sqlglot as sg

In [2]: sg.__version__
Out[2]: '11.4.1'

In [3]: sg.parse_one("select x ~ y", read="postgres")
Out[3]:
(SELECT expressions:
  (REGEXPLIKE this:
    (COLUMN this:
      (IDENTIFIER this: x, quoted: False)), expression:
    (COLUMN this:
      (IDENTIFIER this: y, quoted: False))))

In [4]: sg.parse_one("select x ~ y", read="duckdb")
...
ParseError: Invalid expression / Unexpected token. Line 1, Col: 10.
  select x ~ y
```

`~` is a valid duckdb operator:

```
❯ duckdb
v0.7.1
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
D select 'x' ~ 'y' as m;
┌─────────┐
│    m    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
```


Discussion:
xref: https://github.com/ibis-project/ibis/issues/5807

Resolving patch:
diff --git a/sqlglot/dialects/duckdb.py b/sqlglot/dialects/duckdb.py
--- a/sqlglot/dialects/duckdb.py
+++ b/sqlglot/dialects/duckdb.py
@@ -80,6 +80,7 @@ class DuckDB(Dialect):
     class Tokenizer(tokens.Tokenizer):
         KEYWORDS = {
             **tokens.Tokenizer.KEYWORDS,
+            "~": TokenType.RLIKE,
             ":=": TokenType.EQ,
             "ATTACH": TokenType.COMMAND,
             "BINARY": TokenType.VARBINARY,


Test patch:
diff --git a/tests/dialects/test_duckdb.py b/tests/dialects/test_duckdb.py
--- a/tests/dialects/test_duckdb.py
+++ b/tests/dialects/test_duckdb.py
@@ -125,6 +125,7 @@ def test_duckdb(self):
             "SELECT a['x space'] FROM (SELECT {'x space': 1, 'y': 2, 'z': 3} AS a)"
         )
 
+        self.validate_all("x ~ y", write={"duckdb": "REGEXP_MATCHES(x, y)"})
         self.validate_all("SELECT * FROM 'x.y'", write={"duckdb": 'SELECT * FROM "x.y"'})
         self.validate_all(
             "WITH 'x' AS (SELECT 1) SELECT * FROM x",
Repository: tobymao/sqlglot

Issue:
parsing trino query with `partition` as field name fails
Trino will allow a column name to be called `partition`, but sqlglot will fail to parse it.  Example:

```
>>> query3 = "select partition, b from table_a"
>>> sqlglot.parse(query3, read="trino")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/joshua/.pyenv/versions/3.9.11/lib/python3.9/site-packages/sqlglot/__init__.py", line 72, in parse
    return dialect.parse(sql, **opts)
  File "/Users/joshua/.pyenv/versions/3.9.11/lib/python3.9/site-packages/sqlglot/dialects/dialect.py", line 163, in parse
    return self.parser(**opts).parse(self.tokenize(sql), sql)
  File "/Users/joshua/.pyenv/versions/3.9.11/lib/python3.9/site-packages/sqlglot/parser.py", line 785, in parse
    return self._parse(
  File "/Users/joshua/.pyenv/versions/3.9.11/lib/python3.9/site-packages/sqlglot/parser.py", line 851, in _parse
    self.raise_error("Invalid expression / Unexpected token")
  File "/Users/joshua/.pyenv/versions/3.9.11/lib/python3.9/site-packages/sqlglot/parser.py", line 894, in raise_error
    raise error
sqlglot.errors.ParseError: Invalid expression / Unexpected token. Line 1, Col: 8.
  select partition, b from table_a
```


Discussion:

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -234,6 +234,7 @@ class Parser(metaclass=_Parser):
         TokenType.ONLY,
         TokenType.OPTIONS,
         TokenType.ORDINALITY,
+        TokenType.PARTITION,
         TokenType.PERCENT,
         TokenType.PIVOT,
         TokenType.PRAGMA,


Test patch:
diff --git a/tests/fixtures/identity.sql b/tests/fixtures/identity.sql
--- a/tests/fixtures/identity.sql
+++ b/tests/fixtures/identity.sql
@@ -768,6 +768,7 @@ ALTER TABLE baa ADD CONSTRAINT boo PRIMARY KEY (x, y) NOT ENFORCED DEFERRABLE IN
 ALTER TABLE baa ADD CONSTRAINT boo FOREIGN KEY (x, y) REFERENCES persons ON UPDATE NO ACTION ON DELETE NO ACTION MATCH FULL
 ALTER TABLE a ADD PRIMARY KEY (x, y) NOT ENFORCED
 ALTER TABLE a ADD FOREIGN KEY (x, y) REFERENCES bla
+SELECT partition FROM a
 SELECT end FROM a
 SELECT id FROM b.a AS a QUALIFY ROW_NUMBER() OVER (PARTITION BY br ORDER BY sadf DESC) = 1
 SELECT LEFT.FOO FROM BLA AS LEFT
diff --git a/tests/test_parser.py b/tests/test_parser.py
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -360,7 +360,7 @@ def test_comment_error_r(self, logger):
     @patch("sqlglot.parser.logger")
     def test_create_table_error(self, logger):
         parse_one(
-            """CREATE TABLE PARTITION""",
+            """CREATE TABLE SELECT""",
             error_level=ErrorLevel.WARN,
         )
Repository: tobymao/sqlglot

Issue:
Comment at end of query is removed
Hi,
Could you please help me with this problem?

dialect: trino
version 11.4.5

```
SELECT
  t.name,
  t.tags,
  t.date,
  s.price,
  s.action
FROM "stock prices_grid" AS s
JOIN test_database_1."test data" AS t
  ON s.name = t.name
--test comment will be removed
```

The below code removes the comment at the end which is an unexpected behaviour.
```
expression_tree = parse_one(query, dialect)    
```


Discussion:

Resolving patch:
diff --git a/sqlglot/tokens.py b/sqlglot/tokens.py
--- a/sqlglot/tokens.py
+++ b/sqlglot/tokens.py
@@ -946,7 +946,7 @@ def _scan_comment(self, comment_start: str) -> bool:
 
         # Leading comment is attached to the succeeding token, whilst trailing comment to the preceding.
         # Multiple consecutive comments are preserved by appending them to the current comments list.
-        if comment_start_line == self._prev_token_line:
+        if comment_start_line == self._prev_token_line or self._end:
             self.tokens[-1].comments.extend(self._comments)
             self._comments = []
             self._prev_token_line = self._line


Test patch:
diff --git a/tests/test_tokens.py b/tests/test_tokens.py
--- a/tests/test_tokens.py
+++ b/tests/test_tokens.py
@@ -13,6 +13,7 @@ def test_comment_attachment(self):
             ("foo --comment", ["comment"]),
             ("foo", []),
             ("foo /*comment 1*/ /*comment 2*/", ["comment 1", "comment 2"]),
+            ("foo\n-- comment", [" comment"]),
         ]
 
         for sql, comment in sql_comment:
Repository: tobymao/sqlglot

Issue:
Casting to array of struct with duckdb fails to parse
```
In [17]: import sqlglot as sg

In [18]: sg.__version__
Out[18]: '11.4.5'

In [19]: sg.parse_one("select cast([struct_pack(a := 1)] as struct(a bigint)[])", read="duckdb")
...
ParseError: Expected TYPE after CAST. Line 1, Col: 38.
  select cast([struct_pack(a := 1)] as struct(a bigint)[])
```


Discussion:
thanks, I'll take a look soon

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -2636,7 +2636,7 @@ def _parse_types(self, check_func: bool = False) -> t.Optional[exp.Expression]:
             self._match_r_paren()
             maybe_func = True
 
-        if not nested and self._match_pair(TokenType.L_BRACKET, TokenType.R_BRACKET):
+        if self._match_pair(TokenType.L_BRACKET, TokenType.R_BRACKET):
             this = exp.DataType(
                 this=exp.DataType.Type.ARRAY,
                 expressions=[exp.DataType.build(type_token.value, expressions=expressions)],


Test patch:
diff --git a/tests/dialects/test_duckdb.py b/tests/dialects/test_duckdb.py
--- a/tests/dialects/test_duckdb.py
+++ b/tests/dialects/test_duckdb.py
@@ -432,6 +432,18 @@ def test_cast(self):
                 "snowflake": "CAST(COL AS ARRAY)",
             },
         )
+        self.validate_all(
+            "CAST([STRUCT_PACK(a := 1)] AS STRUCT(a BIGINT)[])",
+            write={
+                "duckdb": "CAST(LIST_VALUE({'a': 1}) AS STRUCT(a BIGINT)[])",
+            },
+        )
+        self.validate_all(
+            "CAST([[STRUCT_PACK(a := 1)]] AS STRUCT(a BIGINT)[][])",
+            write={
+                "duckdb": "CAST(LIST_VALUE(LIST_VALUE({'a': 1})) AS STRUCT(a BIGINT)[][])",
+            },
+        )
 
     def test_bool_or(self):
         self.validate_all(
Repository: tobymao/sqlglot

Issue:
Cannot attach comments to WITH expression 
Hi,

The comment in the below SQL gets removed when the query is parsed.
```
-- test
WITH v AS (
  SELECT
    1 AS literal
)
SELECT
  *
FROM v
```

But the below sql retains the comment,

```
-- test
SELECT
  *
FROM v
```





Discussion:

Resolving patch:
diff --git a/sqlglot/generator.py b/sqlglot/generator.py
--- a/sqlglot/generator.py
+++ b/sqlglot/generator.py
@@ -208,7 +208,7 @@ class Generator:
         exp.WithJournalTableProperty: exp.Properties.Location.POST_NAME,
     }
 
-    WITH_SEPARATED_COMMENTS = (exp.Select, exp.From, exp.Where)
+    WITH_SEPARATED_COMMENTS = (exp.Select, exp.From, exp.Where, exp.With)
 
     SENTINEL_LINE_BREAK = "__SQLGLOT__LB__"
 
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -1799,6 +1799,7 @@ def _parse_with(self, skip_with_token: bool = False) -> t.Optional[exp.Expressio
         if not skip_with_token and not self._match(TokenType.WITH):
             return None
 
+        comments = self._prev_comments
         recursive = self._match(TokenType.RECURSIVE)
 
         expressions = []
@@ -1810,7 +1811,9 @@ def _parse_with(self, skip_with_token: bool = False) -> t.Optional[exp.Expressio
             else:
                 self._match(TokenType.WITH)
 
-        return self.expression(exp.With, expressions=expressions, recursive=recursive)
+        return self.expression(
+            exp.With, comments=comments, expressions=expressions, recursive=recursive
+        )
 
     def _parse_cte(self) -> exp.Expression:
         alias = self._parse_table_alias()


Test patch:
diff --git a/tests/fixtures/identity.sql b/tests/fixtures/identity.sql
--- a/tests/fixtures/identity.sql
+++ b/tests/fixtures/identity.sql
@@ -728,6 +728,7 @@ SELECT x FROM a.b.c /* x */, e.f.g /* x */
 SELECT FOO(x /* c */) /* FOO */, b /* b */
 SELECT FOO(x /* c1 */ + y /* c2 */ + BLA(5 /* c3 */)) FROM (VALUES (1 /* c4 */, "test" /* c5 */)) /* c6 */
 INSERT INTO foo SELECT * FROM bar /* comment */
+/* c */ WITH x AS (SELECT 1) SELECT * FROM x
 SELECT a FROM x WHERE a COLLATE 'utf8_general_ci' = 'b'
 SELECT x AS INTO FROM bla
 SELECT * INTO newevent FROM event
diff --git a/tests/test_transpile.py b/tests/test_transpile.py
--- a/tests/test_transpile.py
+++ b/tests/test_transpile.py
@@ -234,6 +234,27 @@ def test_comments(self):
   foo /* comment 1 */ AND bar AND bla /* comment 2 */""",
             pretty=True,
         )
+        self.validate(
+            """
+            -- test
+            WITH v AS (
+              SELECT
+                1 AS literal
+            )
+            SELECT
+              *
+            FROM v
+            """,
+            """/* test */
+WITH v AS (
+  SELECT
+    1 AS literal
+)
+SELECT
+  *
+FROM v""",
+            pretty=True,
+        )
 
     def test_types(self):
         self.validate("INT 1", "CAST(1 AS INT)")
Repository: tobymao/sqlglot

Issue:
support division in a comment
`select 1 /*/2 */` will raise error, while it is valid query.
As far as I understend issue is that combination /*/ is treated like start and end of comment, while it is not


Discussion:

Resolving patch:
diff --git a/sqlglot/tokens.py b/sqlglot/tokens.py
--- a/sqlglot/tokens.py
+++ b/sqlglot/tokens.py
@@ -953,8 +953,10 @@ def _scan_comment(self, comment_start: str) -> bool:
         comment_end = self._COMMENTS[comment_start]  # type: ignore
 
         if comment_end:
-            comment_end_size = len(comment_end)
+            # Skip the comment's start delimiter
+            self._advance(comment_start_size)
 
+            comment_end_size = len(comment_end)
             while not self._end and self._chars(comment_end_size) != comment_end:
                 self._advance()
 


Test patch:
diff --git a/tests/test_tokens.py b/tests/test_tokens.py
--- a/tests/test_tokens.py
+++ b/tests/test_tokens.py
@@ -14,6 +14,7 @@ def test_comment_attachment(self):
             ("foo", []),
             ("foo /*comment 1*/ /*comment 2*/", ["comment 1", "comment 2"]),
             ("foo\n-- comment", [" comment"]),
+            ("1 /*/2 */", ["/2 "]),
         ]
 
         for sql, comment in sql_comment:
diff --git a/tests/test_transpile.py b/tests/test_transpile.py
--- a/tests/test_transpile.py
+++ b/tests/test_transpile.py
@@ -87,6 +87,7 @@ def test_space(self):
         self.validate("SELECT 3>=3", "SELECT 3 >= 3")
 
     def test_comments(self):
+        self.validate("SELECT 1 /*/2 */", "SELECT 1 /* /2 */")
         self.validate("SELECT */*comment*/", "SELECT * /* comment */")
         self.validate(
             "SELECT * FROM table /*comment 1*/ /*comment 2*/",
Repository: tobymao/sqlglot

Issue:
SQL with INTERVAL key word parse error
```python
from sqlglot import parse_one
sql = """
SELECT DATE(DATE_SUB(`dt`, INTERVAL DAYOFMONTH(`dt`) - 1 DAY)) AS __timestamp
from tableT
"""
expression_tree = parse_one(sql, read="mysql")
print(expression_tree.sql(dialect="mysql", pretty=True))
# Got wrong sql
# SELECT
#   DATE(DATE_SUB(`dt`, INTERVAL (INTERVAL (DAYOFMONTH(`dt`)) - 1) DAY)) AS __timestamp
# FROM tableT


Discussion:
Thanks for the report, I'll take a look shortly.

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -2604,7 +2604,7 @@ def _parse_interval(self) -> t.Optional[exp.Expression]:
         if not self._match(TokenType.INTERVAL):
             return None
 
-        this = self._parse_primary() or self._parse_column()
+        this = self._parse_primary() or self._parse_term()
         unit = self._parse_function() or self._parse_var()
 
         # Most dialects support, e.g., the form INTERVAL '5' day, thus we try to parse


Test patch:
diff --git a/tests/dialects/test_mysql.py b/tests/dialects/test_mysql.py
--- a/tests/dialects/test_mysql.py
+++ b/tests/dialects/test_mysql.py
@@ -317,6 +317,12 @@ def test_mysql_time(self):
         self.validate_identity("TIME_STR_TO_UNIX(x)", "UNIX_TIMESTAMP(x)")
 
     def test_mysql(self):
+        self.validate_all(
+            "SELECT DATE(DATE_SUB(`dt`, INTERVAL DAYOFMONTH(`dt`) - 1 DAY)) AS __timestamp FROM tableT",
+            write={
+                "mysql": "SELECT DATE(DATE_SUB(`dt`, INTERVAL (DAYOFMONTH(`dt`) - 1) DAY)) AS __timestamp FROM tableT",
+            },
+        )
         self.validate_all(
             "SELECT a FROM tbl FOR UPDATE",
             write={
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:

Resolving patch:
diff --git a/sqlglot/dialects/oracle.py b/sqlglot/dialects/oracle.py
--- a/sqlglot/dialects/oracle.py
+++ b/sqlglot/dialects/oracle.py
@@ -165,6 +165,8 @@ def xmltable_sql(self, expression: exp.XMLTable) -> str:
             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,


Test patch:
diff --git a/tests/dialects/test_oracle.py b/tests/dialects/test_oracle.py
--- 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"
Repository: tobymao/sqlglot

Issue:
Oracle's STANDARD_HASH is missing
**Fully reproducible code snippet**
```
sqlglot.parse_one("SELECT STANDARD_HASH('hello', 'SHA256') AS COL1", read="oracle")
```
yields an anonymous function for `standard_hash`.

**Official Documentation**
Please include links to official SQL documentation related to your issue.
https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/STANDARD_HASH.html#GUID-4A68DACE-CFCF-443B-8651-B6CEAA7C4FD7



Discussion:

Resolving patch:
diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py
--- a/sqlglot/expressions.py
+++ b/sqlglot/expressions.py
@@ -4089,6 +4089,10 @@ class Substring(Func):
     arg_types = {"this": True, "start": False, "length": False}
 
 
+class StandardHash(Func):
+    arg_types = {"this": True, "expression": False}
+
+
 class StrPosition(Func):
     arg_types = {
         "this": True,


Test patch:
diff --git a/tests/dialects/test_oracle.py b/tests/dialects/test_oracle.py
--- a/tests/dialects/test_oracle.py
+++ b/tests/dialects/test_oracle.py
@@ -5,6 +5,8 @@ class TestOracle(Validator):
     dialect = "oracle"
 
     def test_oracle(self):
+        self.validate_identity("SELECT STANDARD_HASH('hello')")
+        self.validate_identity("SELECT STANDARD_HASH('hello', 'MD5')")
         self.validate_identity("SELECT * FROM table_name@dblink_name.database_link_domain")
         self.validate_identity("SELECT * FROM table_name SAMPLE (25) s")
         self.validate_identity("SELECT * FROM V$SESSION")
diff --git a/tests/test_expressions.py b/tests/test_expressions.py
--- a/tests/test_expressions.py
+++ b/tests/test_expressions.py
@@ -532,6 +532,7 @@ def test_functions(self):
         self.assertIsInstance(parse_one("YEAR(a)"), exp.Year)
         self.assertIsInstance(parse_one("HLL(a)"), exp.Hll)
         self.assertIsInstance(parse_one("ARRAY(time, foo)"), exp.Array)
+        self.assertIsInstance(parse_one("STANDARD_HASH('hello', 'sha256')"), exp.StandardHash)
 
     def test_column(self):
         column = parse_one("a.b.c.d")
Repository: tobymao/sqlglot

Issue:
`CHAR VARYING` and `NCHAR VARYING` not parsed for Snowflake
Snowflake accepts `CHAR VARYING` and `NCHAR VARYING` as aliases to `VARCHAR`

**Fully reproducible code snippet**
```
import sqlglot
sqlglot.transpile("SELECT CAST(foo as CHAR VARYING) FROM bar", read="snowflake")
```

**Official Documentation**

[Link to the Snowflake docs](https://docs.snowflake.com/en/sql-reference/data-types-text#string-text-nvarchar-nvarchar2-char-varying-nchar-varying): STRING , TEXT , NVARCHAR , NVARCHAR2 , CHAR VARYING , NCHAR VARYING are all equivalent to VARCHAR

(I am happy to contribute to a PR if need be)


Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/snowflake.py b/sqlglot/dialects/snowflake.py
--- a/sqlglot/dialects/snowflake.py
+++ b/sqlglot/dialects/snowflake.py
@@ -263,17 +263,19 @@ class Tokenizer(tokens.Tokenizer):
 
         KEYWORDS = {
             **tokens.Tokenizer.KEYWORDS,
+            "CHAR VARYING": TokenType.VARCHAR,
+            "NCHAR VARYING": TokenType.VARCHAR,
             "EXCLUDE": TokenType.EXCEPT,
             "ILIKE ANY": TokenType.ILIKE_ANY,
             "LIKE ANY": TokenType.LIKE_ANY,
             "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE,
+            "MINUS": TokenType.EXCEPT,
             "PUT": TokenType.COMMAND,
             "RENAME": TokenType.REPLACE,
             "TIMESTAMP_LTZ": TokenType.TIMESTAMPLTZ,
             "TIMESTAMP_NTZ": TokenType.TIMESTAMP,
             "TIMESTAMP_TZ": TokenType.TIMESTAMPTZ,
             "TIMESTAMPNTZ": TokenType.TIMESTAMP,
-            "MINUS": TokenType.EXCEPT,
             "SAMPLE": TokenType.TABLE_SAMPLE,
         }
 


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
@@ -27,6 +27,8 @@ def test_snowflake(self):
         self.validate_identity("COMMENT IF EXISTS ON TABLE foo IS 'bar'")
         self.validate_identity("SELECT CONVERT_TIMEZONE('UTC', 'America/Los_Angeles', col)")
 
+        self.validate_all("CAST(x AS CHAR 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 i, p, o FROM qt QUALIFY ROW_NUMBER() OVER (PARTITION BY p ORDER BY o) = 1",
             write={