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

Issue:
[TSQL] DATENAME is replaced incorrectly
# Issue Description

sqlglot==13.3.0

**Code**
```python
query = "Select DATENAME(dw, some_date) FROM my_table"
query = parse_one(query, dialect='tsql')
print(query)
```

**Output**
```sql
Select FORMAT(some_date, '%A') AS day FROM my_table
```

**Expected Output**
```
Select FORMAT(some_date, 'dddd') AS day FROM my_table
```

## Analysis

> format
nvarchar format pattern.
The format argument must contain a valid .NET Framework format string, either as a standard format string (for example, "C" or "D"), or as a pattern of custom characters for dates and numeric values (for example, "MMMM DD, yyyy (dddd)"). Composite formatting is not supported. For a full explanation of these formatting patterns, consult the .NET Framework documentation on string formatting in general, custom date and time formats, and custom number formats. A good starting point is the topic, "[Formatting Types](https://learn.microsoft.com/en-us/dotnet/standard/base-types/formatting-types)."

The correct format should be `dddd`. See [here](https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings#ddddSpecifier) for more info.


## Additional Question
Could you please provide the rationale behind replacing DATENAME with FORMAT? Also, in general why are some functions replaced but not others?



Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/tsql.py b/sqlglot/dialects/tsql.py
--- a/sqlglot/dialects/tsql.py
+++ b/sqlglot/dialects/tsql.py
@@ -243,6 +243,7 @@ class TSQL(Dialect):
         "MMM": "%b",
         "MM": "%m",
         "M": "%-m",
+        "dddd": "%A",
         "dd": "%d",
         "d": "%-d",
         "HH": "%H",


Test patch:
diff --git a/tests/dialects/test_tsql.py b/tests/dialects/test_tsql.py
--- a/tests/dialects/test_tsql.py
+++ b/tests/dialects/test_tsql.py
@@ -855,12 +855,18 @@ def test_datefromparts(self):
 
     def test_datename(self):
         self.validate_all(
-            "SELECT DATENAME(mm,'1970-01-01')",
-            write={"spark": "SELECT DATE_FORMAT(CAST('1970-01-01' AS TIMESTAMP), 'MMMM')"},
+            "SELECT DATENAME(mm, '1970-01-01')",
+            write={
+                "spark": "SELECT DATE_FORMAT(CAST('1970-01-01' AS TIMESTAMP), 'MMMM')",
+                "tsql": "SELECT FORMAT(CAST('1970-01-01' AS DATETIME2), 'MMMM')",
+            },
         )
         self.validate_all(
-            "SELECT DATENAME(dw,'1970-01-01')",
-            write={"spark": "SELECT DATE_FORMAT(CAST('1970-01-01' AS TIMESTAMP), 'EEEE')"},
+            "SELECT DATENAME(dw, '1970-01-01')",
+            write={
+                "spark": "SELECT DATE_FORMAT(CAST('1970-01-01' AS TIMESTAMP), 'EEEE')",
+                "tsql": "SELECT FORMAT(CAST('1970-01-01' AS DATETIME2), 'dddd')",
+            },
         )
 
     def test_datepart(self):
Repository: tobymao/sqlglot

Issue:
Postgres opclass with schema prefix
**Before you file an issue**
In Postgres SQL opclass may include a schema prefix. Now I get an error when parsing such SQL. 

**Fully reproducible code snippet**
```python
    sql = """
    CREATE INDEX index_issues_on_title_trigram ON public.issues USING gin (title public.gin_trgm_ops);
    """
    parsed_sql_exprs = sqlglot.parse_one(sql, read="postgres")
```

**Official Documentation**
https://www.postgresql.org/docs/current/sql-createopclass.html



Discussion:

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -879,6 +879,7 @@ class Parser(metaclass=_Parser):
     CLONE_KINDS = {"TIMESTAMP", "OFFSET", "STATEMENT"}
 
     OPCLASS_FOLLOW_KEYWORDS = {"ASC", "DESC", "NULLS"}
+    OPTYPE_FOLLOW_TOKENS = {TokenType.COMMA, TokenType.R_PAREN}
 
     TABLE_INDEX_HINT_TOKENS = {TokenType.FORCE, TokenType.IGNORE, TokenType.USE}
 
@@ -2565,9 +2566,8 @@ def _parse_opclass(self) -> t.Optional[exp.Expression]:
         if self._match_texts(self.OPCLASS_FOLLOW_KEYWORDS, advance=False):
             return this
 
-        opclass = self._parse_var(any_token=True)
-        if opclass:
-            return self.expression(exp.Opclass, this=this, expression=opclass)
+        if not self._match_set(self.OPTYPE_FOLLOW_TOKENS, advance=False):
+            return self.expression(exp.Opclass, this=this, expression=self._parse_table_parts())
 
         return this
 


Test patch:
diff --git a/tests/dialects/test_postgres.py b/tests/dialects/test_postgres.py
--- a/tests/dialects/test_postgres.py
+++ b/tests/dialects/test_postgres.py
@@ -42,6 +42,9 @@ def test_ddl(self):
         self.validate_identity(
             "CREATE INDEX foo ON bar.baz USING btree(col1 varchar_pattern_ops ASC, col2)"
         )
+        self.validate_identity(
+            "CREATE INDEX index_issues_on_title_trigram ON public.issues USING gin(title public.gin_trgm_ops)"
+        )
         self.validate_identity(
             "INSERT INTO x VALUES (1, 'a', 2.0) ON CONFLICT (id) DO NOTHING RETURNING *"
         )
Repository: tobymao/sqlglot

Issue:
ALTER TABLE statement with Drop constraint not parsing properly
I was trying to parse a DROP CONSTRAINT statement in oracle and TSQL, but sqlglot.parse_one is not parsing them properly. it does not return the meta data about the drop constraint as it is giving when we add constraint. specifically i am trying it with foreign key. it works perfectly when i add constraint in alter table but does work in drop constraint

`sqlglot.parse_one(`
        `"ALTER TABLE dbo.DocExe DROP CONSTRAINT FK_Column_B;", "tsql"`
   ` )`
   
   The above example is copied from this docs https://learn.microsoft.com/en-us/sql/relational-databases/tables/delete-foreign-key-relationships?view=sql-server-ver16
   



Discussion:
@HassanShafiq123 please link relevant documentation

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -245,6 +245,7 @@ class Parser(metaclass=_Parser):
 
     CREATABLES = {
         TokenType.COLUMN,
+        TokenType.CONSTRAINT,
         TokenType.FUNCTION,
         TokenType.INDEX,
         TokenType.PROCEDURE,


Test patch:
diff --git a/tests/dialects/test_tsql.py b/tests/dialects/test_tsql.py
--- a/tests/dialects/test_tsql.py
+++ b/tests/dialects/test_tsql.py
@@ -561,6 +561,13 @@ def test_types_bin(self):
         )
 
     def test_ddl(self):
+        expression = parse_one("ALTER TABLE dbo.DocExe DROP CONSTRAINT FK_Column_B", dialect="tsql")
+        self.assertIsInstance(expression, exp.AlterTable)
+        self.assertIsInstance(expression.args["actions"][0], exp.Drop)
+        self.assertEqual(
+            expression.sql(dialect="tsql"), "ALTER TABLE dbo.DocExe DROP CONSTRAINT FK_Column_B"
+        )
+
         for clusterd_keyword in ("CLUSTERED", "NONCLUSTERED"):
             self.validate_identity(
                 'CREATE TABLE "dbo"."benchmark" ('
@@ -630,7 +637,6 @@ def test_ddl(self):
                 "tsql": "CREATE OR ALTER VIEW a.b AS SELECT 1",
             },
         )
-
         self.validate_all(
             "ALTER TABLE a ADD b INTEGER, c INTEGER",
             read={
@@ -641,7 +647,6 @@ def test_ddl(self):
                 "tsql": "ALTER TABLE a ADD b INTEGER, c INTEGER",
             },
         )
-
         self.validate_all(
             "CREATE TABLE #mytemp (a INTEGER, b CHAR(2), c TIME(4), d FLOAT(24))",
             write={
Repository: tobymao/sqlglot

Issue:
[Bug] Transpiling built-in functions is not accurate.
**Before you file an issue**
- updated to 19.0.3

**Fully reproducible code snippet**
I am transpiling Oracle SQL to Postgres. There are multiple functions that fail when executed.
Here is an example.
`sql_in_oracle = "to_char(123)"`
`sqlglot.transpile(sql_in_oracle, read='oracle', write='postgres')`

Output: `['to_char(123)']`
Expected: `['123::text']` or whatever is valid in Postgres
Postgres supports `to_char(expr, format)`, but not `to_char(expr)`.

I have many functions that cannot be tranpiled correctly in my query list, such as,

Truncate datetime to day:
TRUNC(datetime) -- Valid Oracle
Output: TRUNC(datetime) -- Invalid Postgres
Expected: DATE_TRUNC('day', datetime) -- Valid postgres



**Official Documentation**
[sqlines](https://sqlines.com/oracle-to-postgresql) has an online tool I tried once. On its website, it lists many migration conversions for different databases. It might be a helpful resource for you to check out. Thanks.


Discussion:
@CBQu please list the correct transpilations and supporting documentation 

Resolving patch:
diff --git a/sqlglot/dialects/oracle.py b/sqlglot/dialects/oracle.py
--- a/sqlglot/dialects/oracle.py
+++ b/sqlglot/dialects/oracle.py
@@ -3,7 +3,13 @@
 import typing as t
 
 from sqlglot import exp, generator, parser, tokens, transforms
-from sqlglot.dialects.dialect import Dialect, no_ilike_sql, rename_func, trim_sql
+from sqlglot.dialects.dialect import (
+    Dialect,
+    format_time_lambda,
+    no_ilike_sql,
+    rename_func,
+    trim_sql,
+)
 from sqlglot.helper import seq_get
 from sqlglot.tokens import TokenType
 
@@ -70,6 +76,7 @@ class Parser(parser.Parser):
         FUNCTIONS = {
             **parser.Parser.FUNCTIONS,
             "SQUARE": lambda args: exp.Pow(this=seq_get(args, 0), expression=exp.Literal.number(2)),
+            "TO_CHAR": format_time_lambda(exp.TimeToStr, "oracle", default=True),
         }
 
         FUNCTION_PARSERS: t.Dict[str, t.Callable] = {


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
@@ -62,6 +62,13 @@ def test_oracle(self):
             "SELECT * FROM t SAMPLE (0.25)",
         )
 
+        self.validate_all(
+            "SELECT TO_CHAR(TIMESTAMP '1999-12-01 10:00:00')",
+            write={
+                "oracle": "SELECT TO_CHAR(CAST('1999-12-01 10:00:00' AS TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS')",
+                "postgres": "SELECT TO_CHAR(CAST('1999-12-01 10:00:00' AS TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS')",
+            },
+        )
         self.validate_all(
             "SELECT CAST(NULL AS VARCHAR2(2328 CHAR)) AS COL1",
             write={
Repository: tobymao/sqlglot

Issue:
List index out of range for Snowflake SQL transpilation
Ran the issue using the latest `main` build `sqlglot-19.0.4.dev18`

Read: `snowflake`
Write `spark` 

When running the following query on Snowflake's publically available documentation, we get an `IndexError: list index out of range`. It's unclear which part of the query is unable to be tokenized. 

Code snippet 

https://docs.snowflake.com/en/sql-reference/sql/create-external-table

```
query_1666 = 'SELECT metadata$filename FROM @s1/;'

transpiled_sqls = transpile(query_1666, read='snowflake', write='spark', pretty=True, error_level=None)
```



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
@@ -349,7 +349,7 @@ def _parse_table_parts(self, schema: bool = False) -> exp.Table:
             table: t.Optional[exp.Expression] = None
             if self._match_text_seq("@"):
                 table_name = "@"
-                while True:
+                while self._curr:
                     self._advance()
                     table_name += self._prev.text
                     if not self._match_set(self.STAGED_FILE_SINGLE_TOKENS, advance=False):


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
@@ -552,6 +552,7 @@ def test_staged_files(self):
             staged_file.sql(dialect="snowflake"),
         )
 
+        self.validate_identity("SELECT metadata$filename FROM @s1/")
         self.validate_identity("SELECT * FROM @~")
         self.validate_identity("SELECT * FROM @~/some/path/to/file.csv")
         self.validate_identity("SELECT * FROM @mystage")
Repository: tobymao/sqlglot

Issue:
# char at the end of field name disappear when using parse_one with tsql dialect
Query = 'SELECT TestSpecialChar.Test# FROM TestSpecialChar'
Using:
 sql = Parse_one(sql=Query, read='tsql')

Returned value is:
 SELECT TestSpecialChar.Test FROM TestSpecialChar


PS. The query is perfectly valid in T-SQL. I used it to test how SQLGlot was behaving with weird characters in text. Test$ is working, but not Test# 


Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/tsql.py b/sqlglot/dialects/tsql.py
--- a/sqlglot/dialects/tsql.py
+++ b/sqlglot/dialects/tsql.py
@@ -354,6 +354,7 @@ class Tokenizer(tokens.Tokenizer):
         IDENTIFIERS = ['"', ("[", "]")]
         QUOTES = ["'", '"']
         HEX_STRINGS = [("0x", ""), ("0X", "")]
+        VAR_SINGLE_TOKENS = {"@", "$", "#"}
 
         KEYWORDS = {
             **tokens.Tokenizer.KEYWORDS,


Test patch:
diff --git a/tests/dialects/test_tsql.py b/tests/dialects/test_tsql.py
--- a/tests/dialects/test_tsql.py
+++ b/tests/dialects/test_tsql.py
@@ -6,6 +6,10 @@ class TestTSQL(Validator):
     dialect = "tsql"
 
     def test_tsql(self):
+        self.validate_identity("SELECT TestSpecialChar.Test# FROM TestSpecialChar")
+        self.validate_identity("SELECT TestSpecialChar.Test@ FROM TestSpecialChar")
+        self.validate_identity("SELECT TestSpecialChar.Test$ FROM TestSpecialChar")
+        self.validate_identity("SELECT TestSpecialChar.Test_ FROM TestSpecialChar")
         self.validate_identity("SELECT TOP (2 + 1) 1")
         self.validate_identity("SELECT * FROM t WHERE NOT c", "SELECT * FROM t WHERE NOT c <> 0")
         self.validate_identity("1 AND true", "1 <> 0 AND (1 = 1)")
Repository: tobymao/sqlglot

Issue:
sqlglot corrupts date_format spec for MySQL
**Before you file an issue**
> - Make sure you specify the "read" dialect eg. parse_one(sql, read="spark")

Yes, `read='mysql'`

> - Check if the issue still exists on main 

Yes

**Fully reproducible code snippet**

> Please include a fully reproducible code snippet or the input sql, dialect, and expected output.

```
In [19]: import sqlglot

In [20]: sqlglot.parse_one("date_format(now(), '%Y-%m-%d %H:%i:00.0000')", read='mysql').sql(dialect='mysql')
Out[20]: "DATE_FORMAT(NOW(), '%Y-%m-%d %H:%M:00.0000')"
```

sqlglot uses `%M` specifier for minute, but in MySQL `%i` should be used.

**Official Documentation**

> Please include links to official SQL documentation related to your issue.

https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format



Discussion:

Resolving patch:
diff --git a/sqlglot/time.py b/sqlglot/time.py
--- a/sqlglot/time.py
+++ b/sqlglot/time.py
@@ -42,6 +42,10 @@ def format_time(
                 end -= 1
                 chars = sym
                 sym = None
+            else:
+                chars = chars[0]
+                end = start + 1
+
             start += len(chars)
             chunks.append(chars)
             current = trie


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
@@ -123,6 +123,7 @@ def test_ddl(self):
         self.validate_identity("ALTER TABLE test_table ALTER COLUMN test_column SET DEFAULT 1")
 
     def test_identity(self):
+        self.validate_identity("SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:00.0000')")
         self.validate_identity("SELECT @var1 := 1, @var2")
         self.validate_identity("UNLOCK TABLES")
         self.validate_identity("LOCK TABLES `app_fields` WRITE")
Repository: tobymao/sqlglot

Issue:
Inaccurate sql generation for DATEPART in T-SQL
Similar to [2586](https://github.com/tobymao/sqlglot/issues/2586) DATEPART function fails for HOUR and WEEKDAY

**Fully reproducible code snippet**
```
query = """SELECT DATEPART(HOUR, date_and_time) AS 'Hour' FROM table """
print(parse_one(quarter_query, 'tsql').sql(dialect='tsql'))

```
this gives `SELECT FORMAT(CAST(date_and_time AS DATETIME2), 'hour') AS "Hour" FROM table` but the [format code](https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings) is 'h' . Similarly for WEEKDAY it gives 'dw' which is not present in the format codes(thought I couldnt find a corresponding code)



Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/tsql.py b/sqlglot/dialects/tsql.py
--- a/sqlglot/dialects/tsql.py
+++ b/sqlglot/dialects/tsql.py
@@ -136,6 +136,9 @@ def _parse_hashbytes(args: t.List) -> exp.Expression:
     return exp.func("HASHBYTES", *args)
 
 
+DATEPART_ONLY_FORMATS = {"dw", "hour", "quarter"}
+
+
 def _format_sql(self: TSQL.Generator, expression: exp.NumberToStr | exp.TimeToStr) -> str:
     fmt = (
         expression.args["format"]
@@ -149,8 +152,8 @@ def _format_sql(self: TSQL.Generator, expression: exp.NumberToStr | exp.TimeToSt
     )
 
     # There is no format for "quarter"
-    if fmt.name.lower() == "quarter":
-        return self.func("DATEPART", "QUARTER", expression.this)
+    if fmt.name.lower() in DATEPART_ONLY_FORMATS:
+        return self.func("DATEPART", fmt.name, expression.this)
 
     return self.func("FORMAT", expression.this, fmt, expression.args.get("culture"))
 


Test patch:
diff --git a/tests/dialects/test_tsql.py b/tests/dialects/test_tsql.py
--- a/tests/dialects/test_tsql.py
+++ b/tests/dialects/test_tsql.py
@@ -891,8 +891,26 @@ def test_datename(self):
         )
 
     def test_datepart(self):
-        self.validate_identity("DATEPART(QUARTER, x)", "DATEPART(QUARTER, CAST(x AS DATETIME2))")
-        self.validate_identity("DATEPART(YEAR, x)", "FORMAT(CAST(x AS DATETIME2), 'yyyy')")
+        self.validate_identity(
+            "DATEPART(QUARTER, x)",
+            "DATEPART(quarter, CAST(x AS DATETIME2))",
+        )
+        self.validate_identity(
+            "DATEPART(YEAR, x)",
+            "FORMAT(CAST(x AS DATETIME2), 'yyyy')",
+        )
+        self.validate_identity(
+            "DATEPART(HOUR, date_and_time)",
+            "DATEPART(hour, CAST(date_and_time AS DATETIME2))",
+        )
+        self.validate_identity(
+            "DATEPART(WEEKDAY, date_and_time)",
+            "DATEPART(dw, CAST(date_and_time AS DATETIME2))",
+        )
+        self.validate_identity(
+            "DATEPART(DW, date_and_time)",
+            "DATEPART(dw, CAST(date_and_time AS DATETIME2))",
+        )
 
         self.validate_all(
             "SELECT DATEPART(month,'1970-01-01')",
Repository: tobymao/sqlglot

Issue:
Transpiling from BigQuery to DuckDB does not support structs
When transpiling from BigQuery to DuckDB, structs are not properly formatted.

Python source to reproduce:

```
import sqlglot

bigquery_sql = """
SELECT
    STRUCT(
        column1 AS column1,
        column2 AS column2,
        column3 AS column3
    ) AS data
FROM source_table
"""

duckdb_sql = sqlglot.transpile(
    bigquery_sql,
    read="bigquery",
    write="duckdb"
)[0]

print(duckdb_sql)
```

Expected:

```
SELECT
    {
        'column1': column1,
        'column2': column2,
        'column3': column3
    } AS data
FROM source_table
```


Result:

```
SELECT
    {
        'column1': ,
        'column2': ,
        'column3': 
    } AS data
FROM source_table
```

Note that the result contains syntax that is not parseable in DuckDB.



Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/duckdb.py b/sqlglot/dialects/duckdb.py
--- a/sqlglot/dialects/duckdb.py
+++ b/sqlglot/dialects/duckdb.py
@@ -85,10 +85,20 @@ def _parse_date_diff(args: t.List) -> exp.Expression:
 
 
 def _struct_sql(self: DuckDB.Generator, expression: exp.Struct) -> str:
-    args = [
-        f"'{e.name or e.this.name}': {self.sql(e.expressions[0]) if isinstance(e, exp.Bracket) else self.sql(e, 'expression')}"
-        for e in expression.expressions
-    ]
+    args: t.List[str] = []
+    for expr in expression.expressions:
+        if isinstance(expr, exp.Alias):
+            key = expr.alias
+            value = expr.this
+        else:
+            key = expr.name or expr.this.name
+            if isinstance(expr, exp.Bracket):
+                value = expr.expressions[0]
+            else:
+                value = expr.expression
+
+        args.append(f"{self.sql(exp.Literal.string(key))}: {self.sql(value)}")
+
     return f"{{{', '.join(args)}}}"
 
 


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
@@ -54,6 +54,13 @@ def test_duckdb(self):
                 },
             )
 
+        self.validate_all(
+            "SELECT {'bla': column1, 'foo': column2, 'bar': column3} AS data FROM source_table",
+            read={
+                "bigquery": "SELECT STRUCT(column1 AS bla, column2 AS foo, column3 AS bar) AS data FROM source_table",
+                "duckdb": "SELECT {'bla': column1, 'foo': column2, 'bar': column3} AS data FROM source_table",
+            },
+        )
         self.validate_all(
             "WITH cte(x) AS (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) SELECT AVG(x) FILTER (WHERE x > 1) FROM cte",
             write={
Repository: tobymao/sqlglot

Issue:
\r\n sometimes causes a parsing error
Repro

```python
from sqlglot import parse_one
parse_one('select a\r\nfrom b')
``` 

It appears that when the fix went in for line numbers, that the advance function skips the \n, but doesn't advance start, so the text becomes \nfrom which doesn't match.


Discussion:

Resolving patch:
diff --git a/sqlglot/tokens.py b/sqlglot/tokens.py
--- a/sqlglot/tokens.py
+++ b/sqlglot/tokens.py
@@ -587,6 +587,7 @@ def _advance(self, i: int = 1, alnum: bool = False) -> None:
             # Ensures we don't count an extra line if we get a \r\n line break sequence
             if self._char == "\r" and self._peek == "\n":
                 i = 2
+                self._start += 1
 
             self._col = 1
             self._line += 1


Test patch:
diff --git a/tests/test_tokens.py b/tests/test_tokens.py
--- a/tests/test_tokens.py
+++ b/tests/test_tokens.py
@@ -71,6 +71,20 @@ def test_token_line_col(self):
         self.assertEqual(tokens[2].line, 2)
         self.assertEqual(tokens[3].line, 3)
 
+    def test_crlf(self):
+        tokens = Tokenizer().tokenize("SELECT a\r\nFROM b")
+        tokens = [(token.token_type, token.text) for token in tokens]
+
+        self.assertEqual(
+            tokens,
+            [
+                (TokenType.SELECT, "SELECT"),
+                (TokenType.VAR, "a"),
+                (TokenType.FROM, "FROM"),
+                (TokenType.VAR, "b"),
+            ],
+        )
+
     def test_command(self):
         tokens = Tokenizer().tokenize("SHOW;")
         self.assertEqual(tokens[0].token_type, TokenType.SHOW)
diff --git a/tests/test_transpile.py b/tests/test_transpile.py
--- a/tests/test_transpile.py
+++ b/tests/test_transpile.py
@@ -89,6 +89,7 @@ def test_space(self):
         self.validate("SELECT MIN(3)>=MIN(2)", "SELECT MIN(3) >= MIN(2)")
         self.validate("SELECT 1>0", "SELECT 1 > 0")
         self.validate("SELECT 3>=3", "SELECT 3 >= 3")
+        self.validate("SELECT a\r\nFROM b", "SELECT a FROM b")
 
     def test_comments(self):
         self.validate(