Skip to content

Commit df507aa

Browse files
authored
fix(databricks)!: GET_JSON_OBJECT roundtrip (#7728)
1 parent 74bef2f commit df507aa

5 files changed

Lines changed: 22 additions & 22 deletions

File tree

sqlglot-integration-tests

sqlglot/generators/databricks.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,6 @@
1010
from sqlglot.generators.spark import SparkGenerator
1111

1212

13-
def _jsonextract_sql(
14-
self: DatabricksGenerator, expression: exp.JSONExtract | exp.JSONExtractScalar
15-
) -> str:
16-
this = self.sql(expression, "this")
17-
expr = self.sql(expression, "expression")
18-
return f"{this}:{expr}"
19-
20-
2113
class DatabricksGenerator(SparkGenerator):
2214
TABLESAMPLE_SEED_KEYWORD = "REPEATABLE"
2315
COPY_PARAMS_ARE_WRAPPED = False
@@ -52,9 +44,10 @@ class DatabricksGenerator(SparkGenerator):
5244
transforms.any_to_exists,
5345
]
5446
),
55-
exp.JSONExtract: _jsonextract_sql,
56-
exp.JSONExtractScalar: _jsonextract_sql,
57-
exp.JSONPathRoot: lambda *_: "",
47+
exp.JSONExtract: lambda self, e: f"{self.sql(e, 'this')}:{self.sql(e, 'expression')}",
48+
exp.JSONPathRoot: lambda self, e: (
49+
"$" if isinstance(e.parent and e.parent.parent, exp.JSONExtractScalar) else ""
50+
),
5851
exp.ToChar: lambda self, e: (
5952
self.cast_sql(exp.Cast(this=e.this, to=exp.DataType(this="STRING")))
6053
if e.args.get("is_numeric")
@@ -98,7 +91,12 @@ def columndef_sql(self, expression: exp.ColumnDef, sep: str = " ") -> str:
9891

9992
def jsonpath_sql(self, expression: exp.JSONPath) -> str:
10093
expression.set("escape", None)
101-
return super().jsonpath_sql(expression)
94+
path = super().jsonpath_sql(expression)
95+
96+
if isinstance(expression.parent, exp.JSONExtractScalar):
97+
return f"{self.dialect.QUOTE_START}{path}{self.dialect.QUOTE_END}"
98+
99+
return path
102100

103101
def uniform_sql(self, expression: exp.Uniform) -> str:
104102
gen = expression.args.get("gen")

tests/dialects/test_databricks.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,6 @@ def test_databricks(self):
141141

142142
self.validate_all(
143143
"SELECT c1:item[1].price",
144-
read={
145-
"spark": "SELECT GET_JSON_OBJECT(c1, '$.item[1].price')",
146-
},
147144
write={
148145
"databricks": "SELECT c1:item[1].price",
149146
"spark": "SELECT GET_JSON_OBJECT(c1, '$.item[1].price')",
@@ -152,8 +149,11 @@ def test_databricks(self):
152149

153150
self.validate_all(
154151
"SELECT GET_JSON_OBJECT(c1, '$.item[1].price')",
152+
read={
153+
"spark": "SELECT GET_JSON_OBJECT(c1, '$.item[1].price')",
154+
},
155155
write={
156-
"databricks": "SELECT c1:item[1].price",
156+
"databricks": "SELECT GET_JSON_OBJECT(c1, '$.item[1].price')",
157157
"spark": "SELECT GET_JSON_OBJECT(c1, '$.item[1].price')",
158158
},
159159
)
@@ -271,7 +271,7 @@ def test_databricks(self):
271271

272272
self.validate_identity(
273273
"""WITH t AS (SELECT '{"x-y": "z"}' AS c) SELECT get_json_object(c, '$.x-y') FROM t""",
274-
"""WITH t AS (SELECT '{"x-y": "z"}' AS c) SELECT c:["x-y"] FROM t""",
274+
"""WITH t AS (SELECT '{"x-y": "z"}' AS c) SELECT GET_JSON_OBJECT(c, '$["x-y"]') FROM t""",
275275
).selects[0].expression.assert_is(exp.JSONPath)
276276

277277
# https://docs.databricks.com/sql/language-manual/functions/colonsign.html
@@ -296,9 +296,11 @@ def test_json(self):
296296
"""SELECT c1:price FROM VALUES ('{ "price": 5 }') AS T(c1)""",
297297
)
298298
self.validate_identity(
299-
"""SELECT GET_JSON_OBJECT(c1, '$.price') FROM VALUES ('{ "price": 5 }') AS T(c1)""",
300-
"""SELECT c1:price FROM VALUES ('{ "price": 5 }') AS T(c1)""",
299+
"""SELECT GET_JSON_OBJECT(c1, '$.price') FROM VALUES ('{ "price": 5 }') AS T(c1)"""
301300
)
301+
self.validate_identity("SELECT GET_JSON_OBJECT(col, path_col)")
302+
self.validate_identity("SELECT GET_JSON_OBJECT(col, CONCAT('$.', field_name))")
303+
self.validate_identity("SELECT GET_JSON_OBJECT(GET_JSON_OBJECT(col, '$[0]'), '$.a')")
302304
self.validate_identity(
303305
"""SELECT raw:`zip code`, raw:`fb:testid`, raw:store['bicycle'], raw:store["zip code"]""",
304306
"""SELECT raw:["zip code"], raw:["fb:testid"], raw:store.bicycle, raw:store["zip code"]""",

tests/dialects/test_hive.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,7 @@ def test_hive(self):
10201020
"hive": """WITH t AS (SELECT '{"x-y": "z"}' AS c) SELECT GET_JSON_OBJECT(c, '$.x-y') FROM t""",
10211021
"spark2": """WITH t AS (SELECT '{"x-y": "z"}' AS c) SELECT GET_JSON_OBJECT(c, '$.x-y') FROM t""",
10221022
"spark": """WITH t AS (SELECT '{"x-y": "z"}' AS c) SELECT GET_JSON_OBJECT(c, '$.x-y') FROM t""",
1023-
"databricks": """WITH t AS (SELECT '{"x-y": "z"}' AS c) SELECT c:["x-y"] FROM t""",
1023+
"databricks": """WITH t AS (SELECT '{"x-y": "z"}' AS c) SELECT GET_JSON_OBJECT(c, '$["x-y"]') FROM t""",
10241024
},
10251025
)
10261026

tests/dialects/test_redshift.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def test_redshift(self):
3232
"""SELECT JSON_EXTRACT_PATH_TEXT('{ "farm": {"barn": { "color": "red", "feed stocked": true }}}', 'farm', 'barn', 'color')""",
3333
write={
3434
"bigquery": """SELECT JSON_EXTRACT_SCALAR('{ "farm": {"barn": { "color": "red", "feed stocked": true }}}', '$.farm.barn.color')""",
35-
"databricks": """SELECT '{ "farm": {"barn": { "color": "red", "feed stocked": true }}}':farm.barn.color""",
35+
"databricks": """SELECT GET_JSON_OBJECT('{ "farm": {"barn": { "color": "red", "feed stocked": true }}}', '$.farm.barn.color')""",
3636
"duckdb": """SELECT '{ "farm": {"barn": { "color": "red", "feed stocked": true }}}' ->> '$.farm.barn.color'""",
3737
"postgres": """SELECT JSON_EXTRACT_PATH_TEXT('{ "farm": {"barn": { "color": "red", "feed stocked": true }}}', 'farm', 'barn', 'color')""",
3838
"presto": """SELECT JSON_EXTRACT_SCALAR('{ "farm": {"barn": { "color": "red", "feed stocked": true }}}', '$.farm.barn.color')""",

0 commit comments

Comments
 (0)