Repository: tobymao/sqlglot

Issue:
Clickhouse SELECT ... FORMAT raises ParseError
**Fully reproducible code snippet**

```
import unittest

from sqlglot import parse_one
from sqlglot.dialects import ClickHouse


class TestClickhouseParseOneSelectFormat(unittest.TestCase):
    def test_parse_one_format_tab_separated(self):
        query = 'SELECT 1 FORMAT TabSeparated'
        ast = parse_one(sql=query, dialect=ClickHouse)
        self.assertIsNotNone(ast)

    def test_parse_one_format_native(self):
        query = 'SELECT 1 FORMAT Native'
        ast = parse_one(sql=query, dialect=ClickHouse)
        self.assertIsNotNone(ast)


if __name__ == '__main__':
    unittest.main()

```
**Native ParseError**

```
           sqlglot.errors.ParseError: Invalid expression / Unexpected token. Line 1, Col: 22.
             SELECT 1 FORMAT Native
```

**TabSeparated ParseError**

```
           sqlglot.errors.ParseError: Invalid expression / Unexpected token. Line 1, Col: 28.
             SELECT 1 FORMAT TabSeparated
```



**Official Documentation**
FORMAT clause official documentation: https://clickhouse.com/docs/en/sql-reference/statements/select/format 

Thanks in advance

Discussion:

Patch:
diff --git a/sqlglot/dialects/clickhouse.py b/sqlglot/dialects/clickhouse.py
index 8cc16be3..22715982 100644
--- a/sqlglot/dialects/clickhouse.py
+++ b/sqlglot/dialects/clickhouse.py
@@ -306,6 +306,10 @@ class ClickHouse(Dialect):
             TokenType.SETTINGS,
         }
 
+        ALIAS_TOKENS = parser.Parser.ALIAS_TOKENS - {
+            TokenType.FORMAT,
+        }
+
         LOG_DEFAULTS_TO_LN = True
 
         QUERY_MODIFIER_PARSERS = {
diff --git a/sqlglot/dialects/redshift.py b/sqlglot/dialects/redshift.py
index f76ba546..a41b6ea8 100644
--- a/sqlglot/dialects/redshift.py
+++ b/sqlglot/dialects/redshift.py
@@ -92,14 +92,6 @@ class Redshift(Postgres):
 
             return self.expression(exp.Pivot, this=table, unpivot=True) if unpivot else table
 
-        def _parse_type_size(self) -> t.Optional[exp.DataTypeParam]:
-            size = super()._parse_type_size()
-
-            if size and isinstance(size.this, exp.Column):
-                size.set("this", exp.var(size.this.name.upper()))
-
-            return size
-
         def _parse_convert(
             self, strict: bool, safe: t.Optional[bool] = None
         ) -> t.Optional[exp.Expression]:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
index 208f3364..9102f8a7 100644
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -405,6 +405,8 @@ class Parser(metaclass=_Parser):
         TokenType.WINDOW,
     }
 
+    ALIAS_TOKENS = ID_VAR_TOKENS
+
     COMMENT_TABLE_ALIAS_TOKENS = TABLE_ALIAS_TOKENS - {TokenType.IS}
 
     UPDATE_ALIAS_TOKENS = TABLE_ALIAS_TOKENS - {TokenType.SET}
@@ -3928,6 +3930,9 @@ class Parser(metaclass=_Parser):
         if not this:
             return None
 
+        if isinstance(this, exp.Column) and not this.table:
+            this = exp.var(this.name.upper())
+
         return self.expression(
             exp.DataTypeParam, this=this, expression=self._parse_var(any_token=True)
         )
@@ -5254,6 +5259,9 @@ class Parser(metaclass=_Parser):
     def _parse_window(
         self, this: t.Optional[exp.Expression], alias: bool = False
     ) -> t.Optional[exp.Expression]:
+        func = this
+        comments = func.comments if isinstance(func, exp.Expression) else None
+
         if self._match_pair(TokenType.FILTER, TokenType.L_PAREN):
             self._match(TokenType.WHERE)
             this = self.expression(
@@ -5299,9 +5307,16 @@ class Parser(metaclass=_Parser):
         else:
             over = self._prev.text.upper()
 
+        if comments:
+            func.comments = None  # type: ignore
+
         if not self._match(TokenType.L_PAREN):
             return self.expression(
-                exp.Window, this=this, alias=self._parse_id_var(False), over=over
+                exp.Window,
+                comments=comments,
+                this=this,
+                alias=self._parse_id_var(False),
+                over=over,
             )
 
         window_alias = self._parse_id_var(any_token=False, tokens=self.WINDOW_ALIAS_TOKENS)
@@ -5334,6 +5349,7 @@ class Parser(metaclass=_Parser):
 
         window = self.expression(
             exp.Window,
+            comments=comments,
             this=this,
             partition_by=partition,
             order=order,
@@ -5385,7 +5401,7 @@ class Parser(metaclass=_Parser):
             self._match_r_paren(aliases)
             return aliases
 
-        alias = self._parse_id_var(any_token) or (
+        alias = self._parse_id_var(any_token, tokens=self.ALIAS_TOKENS) or (
             self.STRING_ALIASES and self._parse_string_as_identifier()
         )
 


Test patch:
diff --git a/tests/dialects/test_clickhouse.py b/tests/dialects/test_clickhouse.py
index 8a40899a..b50c9b1c 100644
--- a/tests/dialects/test_clickhouse.py
+++ b/tests/dialects/test_clickhouse.py
@@ -401,6 +401,11 @@ class TestClickhouse(Validator):
             """INSERT INTO FUNCTION hdfs('hdfs://hdfs1:9000/test', 'TSV', 'name String, column2 UInt32, column3 UInt32') VALUES ('test', 1, 2)""",
         )
 
+        self.validate_identity("SELECT 1 FORMAT TabSeparated")
+        self.validate_identity("SELECT * FROM t FORMAT TabSeparated")
+        self.validate_identity("SELECT FORMAT")
+        self.validate_identity("1 AS FORMAT").assert_is(exp.Alias)
+
     def test_cte(self):
         self.validate_identity("WITH 'x' AS foo SELECT foo")
         self.validate_identity("WITH ['c'] AS field_names SELECT field_names")
diff --git a/tests/dialects/test_redshift.py b/tests/dialects/test_redshift.py
index 411c29eb..896ee451 100644
--- a/tests/dialects/test_redshift.py
+++ b/tests/dialects/test_redshift.py
@@ -504,7 +504,11 @@ FROM (
 
     def test_varchar_max(self):
         self.validate_all(
-            "CREATE TABLE TEST (cola VARCHAR(max))",
+            'CREATE TABLE "TEST" ("cola" VARCHAR(MAX))',
+            read={
+                "redshift": "CREATE TABLE TEST (cola VARCHAR(max))",
+                "tsql": "CREATE TABLE TEST (cola VARCHAR(max))",
+            },
             write={
                 "redshift": 'CREATE TABLE "TEST" ("cola" VARCHAR(MAX))',
             },
diff --git a/tests/test_transpile.py b/tests/test_transpile.py
index d633f75e..0170e230 100644
--- a/tests/test_transpile.py
+++ b/tests/test_transpile.py
@@ -480,6 +480,13 @@ SELECT
 FROM base""",
             pretty=True,
         )
+        self.validate(
+            """-- comment
+SOME_FUNC(arg IGNORE NULLS)
+  OVER (PARTITION BY foo ORDER BY bla) AS col""",
+            "SOME_FUNC(arg IGNORE NULLS) OVER (PARTITION BY foo ORDER BY bla) AS col /* comment */",
+            pretty=True,
+        )
 
     def test_types(self):
         self.validate("INT 1", "CAST(1 AS INT)")