Skip to content

Commit fe13793

Browse files
authored
SNOW-1875145: change json_element to _is_qualified_name (#2946)
<!--- Please answer these questions before creating your pull request. Thanks! ---> 1. Which Jira issue is this PR addressing? Make sure that there is an accompanying issue to your PR. <!--- In this section, please add a Snowflake Jira issue number. Note that if a corresponding GitHub issue exists, you should still include the Snowflake Jira issue number. For example, for GitHub issue #1400, you should add "SNOW-1335071" here. ---> Fixes SNOW-1875145 2. Fill out the following pre-review checklist: - [x] I am adding a new automated test(s) to verify correctness of my new code - [ ] If this test skips Local Testing mode, I'm requesting review from @snowflakedb/local-testing - [ ] I am adding new logging messages - [ ] I am adding a new telemetry message - [ ] I am adding new credentials - [ ] I am adding a new dependency - [ ] If this is a new feature/behavior, I'm adding the Local Testing parity changes. - [x] I acknowledge that I have ensured my changes to be thread-safe. Follow the link for more information: [Thread-safe Developer Guidelines](https://github.com/snowflakedb/snowpark-python/blob/main/CONTRIBUTING.md#thread-safe-development) 3. Please describe how your code solves the related issue. Please write a short description of how your code change solves the related issue.
1 parent 2312206 commit fe13793

File tree

4 files changed

+55
-44
lines changed

4 files changed

+55
-44
lines changed

CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
#### Experimental Features
6161

6262
- Added `Catalog` class to manage snowflake objects. It can be accessed via `Session.catalog`.
63-
- Added support for querying json element of a VARIANT column in `functions.col` and `functions.column` with an optional keyword argument `json_element`.
6463
- Allow user input schema when reading JSON file on stage.
6564
- Added support for specifying a schema string (including implicit struct syntax) when calling `DataFrame.create_dataframe`.
6665
- `snowflake.core` is a dependency required for this feature.

src/snowflake/snowpark/column.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,14 @@ def __init__(
252252
self,
253253
expr1: Union[str, Expression],
254254
expr2: Optional[str] = None,
255-
json_element: bool = False,
256255
_ast: Optional[proto.Expr] = None,
257256
_emit_ast: bool = True,
257+
*,
258+
_is_qualified_name: bool = False,
258259
) -> None:
259260
self._ast = _ast
260261

261-
def derive_json_element_expr(
262+
def derive_qualified_name_expr(
262263
expr: str, df_alias: Optional[str] = None
263264
) -> UnresolvedAttribute:
264265
parts = expr.split(".")
@@ -281,8 +282,8 @@ def derive_json_element_expr(
281282

282283
if expr2 == "*":
283284
self._expression = Star([], df_alias=expr1)
284-
elif json_element:
285-
self._expression = derive_json_element_expr(expr2, expr1)
285+
elif _is_qualified_name:
286+
self._expression = derive_qualified_name_expr(expr2, expr1)
286287
else:
287288
self._expression = UnresolvedAttribute(
288289
quote_name(expr2), df_alias=expr1
@@ -297,8 +298,8 @@ def derive_json_element_expr(
297298
elif isinstance(expr1, str):
298299
if expr1 == "*":
299300
self._expression = Star([])
300-
elif json_element:
301-
self._expression = derive_json_element_expr(expr1)
301+
elif _is_qualified_name:
302+
self._expression = derive_qualified_name_expr(expr1)
302303
else:
303304
self._expression = UnresolvedAttribute(quote_name(expr1))
304305

@@ -1505,12 +1506,13 @@ class CaseExpr(Column):
15051506
def __init__(
15061507
self,
15071508
expr: CaseWhen,
1508-
json_element: bool = False,
15091509
_ast: Optional[proto.Expr] = None,
15101510
_emit_ast: bool = True,
1511+
*,
1512+
_is_qualified_name: bool = False,
15111513
) -> None:
15121514
super().__init__(
1513-
expr, json_element=json_element, _ast=_ast, _emit_ast=_emit_ast
1515+
expr, _is_qualified_name=_is_qualified_name, _ast=_ast, _emit_ast=_emit_ast
15141516
)
15151517
self._branches = expr.branches
15161518

src/snowflake/snowpark/functions.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -263,30 +263,30 @@ def _check_column_parameters(name1: str, name2: Optional[str]) -> None:
263263

264264
@overload
265265
@publicapi
266-
def col(col_name: str, json_element: bool = False, _emit_ast: bool = True) -> Column:
266+
def col(
267+
col_name: str, _emit_ast: bool = True, *, _is_qualified_name: bool = False
268+
) -> Column:
267269
"""Returns the :class:`~snowflake.snowpark.Column` with the specified name.
268270
269271
Args:
270272
col_name: The name of the column.
271-
json_element: Whether the column is a JSON element. If a column is a VARIANT column in Snowflake,
272-
you can dot notation `.` to query the nested json element, e.g., "name.firstname" and "name.lastname".
273273
274274
Example::
275275
>>> df = session.sql("select 1 as a")
276276
>>> df.select(col("a")).collect()
277277
[Row(A=1)]
278-
279-
>>> df = session.sql("select parse_json('{\"firstname\": \"John\", \"lastname\": \"Doe\"}') as name")
280-
>>> df.select(col("name.firstname", json_element=True)).collect()
281-
[Row(FIRSTNAME='John')]
282278
"""
283279
... # pragma: no cover
284280

285281

286282
@overload
287283
@publicapi
288284
def col(
289-
df_alias: str, col_name: str, json_element: bool = False, _emit_ast: bool = True
285+
df_alias: str,
286+
col_name: str,
287+
_emit_ast: bool = True,
288+
*,
289+
_is_qualified_name: bool = False,
290290
) -> Column:
291291
"""Returns the :class:`~snowflake.snowpark.Column` with the specified dataframe alias and column name.
292292
@@ -302,8 +302,9 @@ def col(
302302
def col(
303303
name1: str,
304304
name2: Optional[str] = None,
305-
json_element: bool = False,
306305
_emit_ast: bool = True,
306+
*,
307+
_is_qualified_name: bool = False,
307308
) -> Column:
308309

309310
_check_column_parameters(name1, name2)
@@ -313,37 +314,37 @@ def col(
313314
ast = create_ast_for_column(name1, name2, "col")
314315

315316
if name2 is None:
316-
return Column(name1, json_element=json_element, _ast=ast)
317+
return Column(name1, _is_qualified_name=_is_qualified_name, _ast=ast)
317318
else:
318-
return Column(name1, name2, json_element=json_element, _ast=ast)
319+
return Column(name1, name2, _is_qualified_name=_is_qualified_name, _ast=ast)
319320

320321

321322
@overload
322323
@publicapi
323-
def column(col_name: str, json_element: bool = False, _emit_ast: bool = True) -> Column:
324+
def column(
325+
col_name: str, _emit_ast: bool = True, *, _is_qualified_name: bool = False
326+
) -> Column:
324327
"""Returns a :class:`~snowflake.snowpark.Column` with the specified name. Alias for col.
325328
326329
Args:
327330
col_name: The name of the column.
328-
json_element: Whether the column is a JSON element. If a column is a VARIANT column in Snowflake,
329-
you can dot notation `.` to query the nested json element, e.g., "name.firstname" and "name.lastname".
330331
331332
Example::
332333
>>> df = session.sql("select 1 as a")
333334
>>> df.select(column("a")).collect()
334335
[Row(A=1)]
335-
336-
>>> df = session.sql("select parse_json('{\"firstname\": \"John\", \"lastname\": \"Doe\"}') as name")
337-
>>> df.select(column("name.firstname", json_element=True)).collect()
338-
[Row(FIRSTNAME='John')]
339336
"""
340337
... # pragma: no cover
341338

342339

343340
@overload
344341
@publicapi
345342
def column(
346-
df_alias: str, col_name: str, json_element: bool = False, _emit_ast: bool = True
343+
df_alias: str,
344+
col_name: str,
345+
_emit_ast: bool = True,
346+
*,
347+
_is_qualified_name: bool = False,
347348
) -> Column:
348349
"""Returns a :class:`~snowflake.snowpark.Column` with the specified name and dataframe alias name. Alias for col.
349350
@@ -359,17 +360,18 @@ def column(
359360
def column(
360361
name1: str,
361362
name2: Optional[str] = None,
362-
json_element: bool = False,
363363
_emit_ast: bool = True,
364+
*,
365+
_is_qualified_name: bool = False,
364366
) -> Column:
365367
_check_column_parameters(name1, name2)
366368

367369
ast = create_ast_for_column(name1, name2, "column") if _emit_ast else None
368370

369371
if name2 is None:
370-
return Column(name1, json_element=json_element, _ast=ast)
372+
return Column(name1, _is_qualified_name=_is_qualified_name, _ast=ast)
371373
else:
372-
return Column(name1, name2, json_element=json_element, _ast=ast)
374+
return Column(name1, name2, _is_qualified_name=_is_qualified_name, _ast=ast)
373375

374376

375377
@publicapi

tests/integ/test_function.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -187,46 +187,54 @@
187187

188188
@pytest.mark.skipif(
189189
"config.getoption('local_testing_mode', default=False)",
190-
reason="querying json element is not supported in local testing",
190+
reason="querying qualified name is not supported in local testing",
191191
)
192-
def test_col_json_element(session):
192+
def test_col_is_qualified_name(session):
193193
# 2-level deep
194194
df = session.sql(
195195
'select parse_json(\'{"firstname": "John", "lastname": "Doe"}\') as name'
196196
)
197197
Utils.check_answer(
198198
df.select(
199-
col("name.firstname", json_element=True),
200-
col("name.lastname", json_element=True),
199+
col("name.firstname", _is_qualified_name=True),
200+
col("name.lastname", _is_qualified_name=True),
201201
),
202202
[Row('"John"', '"Doe"')],
203203
)
204204
Utils.check_answer(
205205
df.select(
206-
col('name."firstname"', json_element=True),
207-
col('NAME."lastname"', json_element=True),
206+
col('name."firstname"', _is_qualified_name=True),
207+
col('NAME."lastname"', _is_qualified_name=True),
208208
),
209209
[Row('"John"', '"Doe"')],
210210
)
211-
Utils.check_answer(df.select(col("name.FIRSTNAME", json_element=True)), [Row(None)])
211+
Utils.check_answer(
212+
df.select(col("name.FIRSTNAME", _is_qualified_name=True)), [Row(None)]
213+
)
212214

213215
# 3-level deep
214216
with pytest.raises(SnowparkSQLException, match="invalid identifier"):
215-
df.select(col("name:firstname", json_element=True)).collect()
217+
df.select(col("name:firstname", _is_qualified_name=True)).collect()
216218

217219
with pytest.raises(SnowparkSQLException, match="invalid identifier"):
218220
df.select(col("name.firstname")).collect()
219221

220222
df = session.sql('select parse_json(\'{"l1": {"l2": "xyz"}}\') as value')
221-
Utils.check_answer(df.select(col("value.l1.l2", json_element=True)), Row('"xyz"'))
222223
Utils.check_answer(
223-
df.select(col('value."l1"."l2"', json_element=True)), Row('"xyz"')
224+
df.select(col("value.l1.l2", _is_qualified_name=True)), Row('"xyz"')
225+
)
226+
Utils.check_answer(
227+
df.select(col('value."l1"."l2"', _is_qualified_name=True)), Row('"xyz"')
228+
)
229+
Utils.check_answer(
230+
df.select(col("value.L1.l2", _is_qualified_name=True)), Row(None)
231+
)
232+
Utils.check_answer(
233+
df.select(col("value.l1.L2", _is_qualified_name=True)), Row(None)
224234
)
225-
Utils.check_answer(df.select(col("value.L1.l2", json_element=True)), Row(None))
226-
Utils.check_answer(df.select(col("value.l1.L2", json_element=True)), Row(None))
227235

228236
with pytest.raises(SnowparkSQLException, match="invalid identifier"):
229-
df.select(col("value:l1.l2", json_element=True)).collect()
237+
df.select(col("value:l1.l2", _is_qualified_name=True)).collect()
230238

231239
with pytest.raises(SnowparkSQLException, match="invalid identifier"):
232240
df.select(col("value.l1.l2")).collect()

0 commit comments

Comments
 (0)