This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new ed08999e22 Fix ODBC Hook sql select return empty table (#36709)
ed08999e22 is described below
commit ed08999e2204f4d8871dbd0448b9897a8dcc0c3b
Author: Roel <[email protected]>
AuthorDate: Wed Jan 10 19:57:21 2024 +0100
Fix ODBC Hook sql select return empty table (#36709)
* feat: return empty list on querying empty table
* feat: return empty list on querying empty table
* feat: added test for empty result
* feat: unsure of an empty return on databricks
* Update tests/providers/odbc/hooks/test_odbc.py
reformatting
Co-authored-by: Wei Lee <[email protected]>
---------
Co-authored-by: Wei Lee <[email protected]>
---
airflow/providers/odbc/hooks/odbc.py | 2 ++
tests/providers/odbc/hooks/test_odbc.py | 17 +++++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/airflow/providers/odbc/hooks/odbc.py
b/airflow/providers/odbc/hooks/odbc.py
index 80ea09c9e8..7b0c4d11e9 100644
--- a/airflow/providers/odbc/hooks/odbc.py
+++ b/airflow/providers/odbc/hooks/odbc.py
@@ -233,6 +233,8 @@ class OdbcHook(DbApiHook):
# Below ignored lines respect NamedTuple docstring, but mypy do not
support dynamically
# instantiated typed Namedtuple, and will never do:
https://github.com/python/mypy/issues/848
field_names: list[tuple[str, type]] | None = None
+ if not result:
+ return []
if isinstance(result, Sequence):
field_names = [col[:2] for col in result[0].cursor_description]
row_object = NamedTuple("Row", field_names) # type: ignore[misc]
diff --git a/tests/providers/odbc/hooks/test_odbc.py
b/tests/providers/odbc/hooks/test_odbc.py
index 391a766df9..64683d21e1 100644
--- a/tests/providers/odbc/hooks/test_odbc.py
+++ b/tests/providers/odbc/hooks/test_odbc.py
@@ -329,6 +329,23 @@ class TestOdbcHook:
result = hook.run("SQL", handler=mock_handler)
assert hook_result == result
+ def test_query_return_serializable_result_empty(self, pyodbc_row_mock,
monkeypatch, pyodbc_instancecheck):
+ """
+ Simulate a cursor.fetchall which returns an iterable of pyodbc.Row
object, and check if this iterable
+ get converted into a list of tuples.
+ """
+ pyodbc_result = []
+ hook_result = []
+
+ def mock_handler(*_):
+ return pyodbc_result
+
+ hook = self.get_hook()
+ with monkeypatch.context() as patcher:
+ patcher.setattr("pyodbc.Row", pyodbc_instancecheck)
+ result = hook.run("SQL", handler=mock_handler)
+ assert hook_result == result
+
def test_query_return_serializable_result_with_fetchone(
self, pyodbc_row_mock, monkeypatch, pyodbc_instancecheck
):