Repository: tobymao/sqlglot

Issue:
Fails to produce SQL representation of transformed tree when a JSON key has a `-`
Having a dash in the key is valid but sqlglot warns against it and raises a `ValueError`

`2024-03-20 21:44:30 [ WARNING] Invalid JSON path syntax. Unexpected TokenType.DASH at index 1: en-US (dialect.py:485)`

` ValueError: Expected an Expression. Received <class 'bool'>: True`


```py
import sqlglot 

sql = """
    SELECT ("data" ->> 'en-US') AS "acat" FROM "my_table" 
    """
parsed_query = sqlglot.parse_one(sql, read="postgres")

def transformer(node):
    ### Actually doing stuff with the node but for example just returning it ###
    return node

transformed_tree = parsed_query.transform(transformer)

## Fails to parse with '-' in the json key.
modified_sql_query = transformed_tree.sql(dialect="postgres")
```


Discussion:
@georgesittas it looks like ->> is calling to_json_path, but i don't think postgres ->> x is a json path, i think it's just a key

Resolving patch:
diff --git a/sqlglot/dialects/dialect.py b/sqlglot/dialects/dialect.py
--- a/sqlglot/dialects/dialect.py
+++ b/sqlglot/dialects/dialect.py
@@ -1019,7 +1019,7 @@ def normalize(identifier: t.Optional[exp.Identifier]) -> t.Optional[str]:
 
 
 def build_json_extract_path(
-    expr_type: t.Type[F], zero_based_indexing: bool = True
+    expr_type: t.Type[F], zero_based_indexing: bool = True, arrow_req_json_type: bool = False
 ) -> t.Callable[[t.List], F]:
     def _builder(args: t.List) -> F:
         segments: t.List[exp.JSONPathPart] = [exp.JSONPathRoot()]
@@ -1039,7 +1039,11 @@ def _builder(args: t.List) -> F:
 
         # This is done to avoid failing in the expression validator due to the arg count
         del args[2:]
-        return expr_type(this=seq_get(args, 0), expression=exp.JSONPath(expressions=segments))
+        return expr_type(
+            this=seq_get(args, 0),
+            expression=exp.JSONPath(expressions=segments),
+            only_json_types=arrow_req_json_type,
+        )
 
     return _builder
 
diff --git a/sqlglot/dialects/postgres.py b/sqlglot/dialects/postgres.py
--- a/sqlglot/dialects/postgres.py
+++ b/sqlglot/dialects/postgres.py
@@ -357,6 +357,16 @@ class Parser(parser.Parser):
 
         JSON_ARROWS_REQUIRE_JSON_TYPE = True
 
+        COLUMN_OPERATORS = {
+            **parser.Parser.COLUMN_OPERATORS,
+            TokenType.ARROW: lambda self, this, path: build_json_extract_path(
+                exp.JSONExtract, arrow_req_json_type=self.JSON_ARROWS_REQUIRE_JSON_TYPE
+            )([this, path]),
+            TokenType.DARROW: lambda self, this, path: build_json_extract_path(
+                exp.JSONExtractScalar, arrow_req_json_type=self.JSON_ARROWS_REQUIRE_JSON_TYPE
+            )([this, path]),
+        }
+
         def _parse_operator(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
             while True:
                 if not self._match(TokenType.L_PAREN):


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
@@ -108,6 +108,8 @@ def test_postgres(self):
         self.validate_identity(
             "SELECT * FROM foo, LATERAL (SELECT * FROM bar WHERE bar.id = foo.bar_id) AS ss"
         )
+        self.validate_identity("SELECT ('data' -> 'en-US') AS acat FROM my_table")
+        self.validate_identity("SELECT ('data' ->> 'en-US') AS acat FROM my_table")
         self.validate_identity(
             "SELECT c.oid, n.nspname, c.relname "
             "FROM pg_catalog.pg_class AS c "