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
     ):

Reply via email to