Repository: tobymao/sqlglot

Issue:
Comments starting with `//` throws a ParseError in Snowflake ❄️ 
_Note: it's absolutely not important since we can just replace them by `--` - just thought I'd write an issue either way_

The following query works in Snowflake:
```sql
SELECT 1 // hi this is a comment
```

But throws a ParseError when parsed:
```py
parse_one("SELECT 1 // hi this is a comment", read=dialects.Snowflake)
```

<details><summary>Here is the traceback</summary>
<p>

```py
Traceback (most recent call last):
  File "/Users/florian.ernst/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/231.9011.38/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py", line 364, in runcode
    coro = func()
  File "<input>", line 1, in <module>
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/__init__.py", line 158, in parse_one
    result = dialect.parse(sql, **opts)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/dialects/dialect.py", line 217, in parse
    return self.parser(**opts).parse(self.tokenize(sql), sql)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 856, in parse
    return self._parse(
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 922, in _parse
    expressions.append(parse_method(self))
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 1112, in _parse_statement
    expression = self._parse_set_operations(expression) if expression else self._parse_select()
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 1877, in _parse_select
    expressions = self._parse_csv(self._parse_expression)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 4135, in _parse_csv
    parse_result = parse_method()
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 2722, in _parse_expression
    return self._parse_alias(self._parse_conjunction())
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 2725, in _parse_conjunction
    return self._parse_tokens(self._parse_equality, self.CONJUNCTION)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 4149, in _parse_tokens
    this = parse_method()
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 2728, in _parse_equality
    return self._parse_tokens(self._parse_comparison, self.EQUALITY)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 4149, in _parse_tokens
    this = parse_method()
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 2731, in _parse_comparison
    return self._parse_tokens(self._parse_range, self.COMPARISON)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 4149, in _parse_tokens
    this = parse_method()
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 2734, in _parse_range
    this = self._parse_bitwise()
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 2831, in _parse_bitwise
    this = self._parse_term()
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 2852, in _parse_term
    return self._parse_tokens(self._parse_factor, self.TERM)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 4149, in _parse_tokens
    this = parse_method()
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 2855, in _parse_factor
    return self._parse_tokens(self._parse_unary, self.FACTOR)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 4152, in _parse_tokens
    this = self.expression(
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 986, in expression
    return self.validate_expression(instance)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 1006, in validate_expression
    self.raise_error(error_message)
  File "/Users/florian.ernst/Alan/alan-jobs/env/lib/python3.10/site-packages/sqlglot/parser.py", line 966, in raise_error
    raise error
sqlglot.errors.ParseError: Required keyword: 'expression' missing for <class 'sqlglot.expressions.Div'>. Line 1, Col: 11.
  SELECT 1 // hi this is a comment
```

</p>
</details> 


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
@@ -269,6 +269,7 @@ class Tokenizer(tokens.Tokenizer):
         QUOTES = ["'", "$$"]
         STRING_ESCAPES = ["\\", "'"]
         HEX_STRINGS = [("x'", "'"), ("X'", "'")]
+        COMMENTS = ["--", "//", ("/*", "*/")]
 
         KEYWORDS = {
             **tokens.Tokenizer.KEYWORDS,
diff --git a/sqlglot/tokens.py b/sqlglot/tokens.py
--- a/sqlglot/tokens.py
+++ b/sqlglot/tokens.py
@@ -392,10 +392,13 @@ def _quotes_to_format(
 
         klass._STRING_ESCAPES = set(klass.STRING_ESCAPES)
         klass._IDENTIFIER_ESCAPES = set(klass.IDENTIFIER_ESCAPES)
-        klass._COMMENTS = dict(
-            (comment, None) if isinstance(comment, str) else (comment[0], comment[1])
-            for comment in klass.COMMENTS
-        )
+        klass._COMMENTS = {
+            **dict(
+                (comment, None) if isinstance(comment, str) else (comment[0], comment[1])
+                for comment in klass.COMMENTS
+            ),
+            "{#": "#}",  # Ensure Jinja comments are tokenized correctly in all dialects
+        }
 
         klass._KEYWORD_TRIE = new_trie(
             key.upper()
@@ -735,7 +738,7 @@ class Tokenizer(metaclass=_Tokenizer):
     NUMERIC_LITERALS: t.Dict[str, str] = {}
     ENCODE: t.Optional[str] = None
 
-    COMMENTS = ["--", ("/*", "*/"), ("{#", "#}")]
+    COMMENTS = ["--", ("/*", "*/")]
 
     __slots__ = (
         "sql",


Test patch:
diff --git a/tests/test_tokens.py b/tests/test_tokens.py
--- a/tests/test_tokens.py
+++ b/tests/test_tokens.py
@@ -1,5 +1,6 @@
 import unittest
 
+from sqlglot.dialects import BigQuery
 from sqlglot.tokens import Tokenizer, TokenType
 
 
@@ -68,7 +69,8 @@ def test_error_msg(self):
             Tokenizer().tokenize("select /*")
 
     def test_jinja(self):
-        tokenizer = Tokenizer()
+        # Check that {#, #} are treated as token delimiters, even though BigQuery overrides COMMENTS
+        tokenizer = BigQuery.Tokenizer()
 
         tokens = tokenizer.tokenize(
             """
diff --git a/tests/test_transpile.py b/tests/test_transpile.py
--- a/tests/test_transpile.py
+++ b/tests/test_transpile.py
@@ -280,6 +280,11 @@ def test_comments(self):
             "select * from t where ((condition = 1)/*test*/)",
             "SELECT * FROM t WHERE ((condition = 1) /* test */)",
         )
+        self.validate(
+            "SELECT 1 // hi this is a comment",
+            "SELECT 1 /* hi this is a comment */",
+            read="snowflake",
+        )
 
     def test_types(self):
         self.validate("INT 1", "CAST(1 AS INT)")