Skip to content

Commit 0b93e03

Browse files
fix: normalize kernel rowcount access
Signed-off-by: Aakash Saravanan <aakash.saravanan@databricks.com>
1 parent d2b58f1 commit 0b93e03

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

‎src/databricks/sql/backend/kernel/client.py‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ def _async_statement_reader(owner: Any) -> Any:
138138
return reader()
139139

140140

141+
def _read_num_modified_rows(handle: Any) -> Optional[int]:
142+
try:
143+
modified = getattr(handle, "num_modified_rows", None)
144+
return modified() if callable(modified) else modified
145+
except Exception:
146+
return None
147+
148+
141149
def _catalog_or_none(value: Optional[str]) -> Optional[str]:
142150
"""Map supported all-catalog wildcards to the kernel's unset filter."""
143151
if value is None or value in ("%", "*"):
@@ -691,12 +699,7 @@ def execute_command(
691699
# default. ``getattr`` guards against an older kernel wheel that
692700
# predates the pyo3 getter. NB the Thrift backend also hardcodes
693701
# ``-1`` here, so this makes the kernel path *exceed* Thrift.
694-
try:
695-
modified = getattr(executed, "num_modified_rows", None)
696-
if callable(modified):
697-
modified = modified()
698-
except Exception:
699-
modified = None
702+
modified = _read_num_modified_rows(executed)
700703
if modified is not None:
701704
cursor.rowcount = modified
702705
# ``KernelResultSet.__init__`` calls ``arrow_schema()`` which
@@ -969,7 +972,7 @@ def get_execution_result(
969972
result_set = self._make_result_set(stream, cursor, command_id)
970973
# Older kernel wheels do not expose this value. Keep them compatible
971974
# while allowing a newer binding to populate async rowcount.
972-
result_set.num_modified_rows = getattr(handle, "num_modified_rows", None)
975+
result_set.num_modified_rows = _read_num_modified_rows(handle)
973976
return result_set
974977
except Exception as exc:
975978
raise _wrap_kernel_exception("get_execution_result", exc) from exc

‎tests/unit/test_kernel_client.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,25 @@ def test_get_query_state_uses_reader_after_result_stream_started():
12331233
reader.status.assert_called_once_with()
12341234

12351235

1236+
class _RaisingModifiedRows:
1237+
@property
1238+
def num_modified_rows(self):
1239+
raise RuntimeError("unavailable")
1240+
1241+
1242+
@pytest.mark.parametrize(
1243+
("handle", "expected"),
1244+
[
1245+
(types.SimpleNamespace(num_modified_rows=7), 7),
1246+
(types.SimpleNamespace(num_modified_rows=lambda: 8), 8),
1247+
(types.SimpleNamespace(), None),
1248+
(_RaisingModifiedRows(), None),
1249+
],
1250+
)
1251+
def test_read_num_modified_rows_compatibility_shapes(handle, expected):
1252+
assert kernel_client._read_num_modified_rows(handle) == expected
1253+
1254+
12361255
@pytest.mark.parametrize("count", [7, 0, None, "unavailable"])
12371256
@pytest.mark.parametrize("source", ["owner", "reader", "attached"])
12381257
def test_async_result_count_after_await(source, count):

0 commit comments

Comments
 (0)