This is an automated email from the ASF dual-hosted git repository.

msyavuz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new ecc7f726a4e fix: guard potential null derefs and remove dead branches 
(#42358)
ecc7f726a4e is described below

commit ecc7f726a4ea2694ed888bcc2429624f3d4c3f1e
Author: Mehmet Salih Yavuz <[email protected]>
AuthorDate: Tue Jul 28 11:43:46 2026 +0300

    fix: guard potential null derefs and remove dead branches (#42358)
    
    Co-authored-by: Enzo Martellucci <[email protected]>
---
 superset/common/query_context_factory.py           |  2 +-
 superset/common/utils/query_cache_manager.py       |  6 ++--
 superset/db_engine_specs/databricks.py             |  1 +
 superset/db_engine_specs/presto.py                 |  3 +-
 .../common/test_query_context_factory.py           | 36 ++++++++++++++++++++++
 5 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/superset/common/query_context_factory.py 
b/superset/common/query_context_factory.py
index 50807370495..57d5494d8e9 100644
--- a/superset/common/query_context_factory.py
+++ b/superset/common/query_context_factory.py
@@ -318,7 +318,7 @@ class QueryContextFactory:  # pylint: 
disable=too-few-public-methods
             # another temporal filter. A new filter based on the value of
             # the granularity will be added later in the code.
             # In practice, this is replacing the previous default temporal 
filter.
-            if is_adhoc_column(filter_to_remove):  # type: ignore
+            if filter_to_remove and is_adhoc_column(filter_to_remove):  # 
type: ignore
                 filter_to_remove = filter_to_remove.get("sqlExpression")
 
             if filter_to_remove:
diff --git a/superset/common/utils/query_cache_manager.py 
b/superset/common/utils/query_cache_manager.py
index 6d7b64041a5..adaf8293b42 100644
--- a/superset/common/utils/query_cache_manager.py
+++ b/superset/common/utils/query_cache_manager.py
@@ -206,11 +206,9 @@ class QueryCacheManager:
                 )
                 query_cache.status = QueryStatus.SUCCESS
                 query_cache.is_loaded = True
-                query_cache.is_cached = cache_value is not None
+                query_cache.is_cached = True
                 query_cache.sql_rowcount = cache_value.get("sql_rowcount", 
None)
-                query_cache.cache_dttm = (
-                    cache_value["dttm"] if cache_value is not None else None
-                )
+                query_cache.cache_dttm = cache_value["dttm"]
                 query_cache.queried_dttm = cache_value.get(
                     "queried_dttm", cache_value.get("dttm")
                 )
diff --git a/superset/db_engine_specs/databricks.py 
b/superset/db_engine_specs/databricks.py
index 255a8c15909..17531c74067 100644
--- a/superset/db_engine_specs/databricks.py
+++ b/superset/db_engine_specs/databricks.py
@@ -534,6 +534,7 @@ class DatabricksDynamicBaseEngineSpec(BasicParametersMixin, 
DatabricksBaseEngine
         ],
     ) -> list[SupersetError]:
         errors: list[SupersetError] = []
+        connect_args: dict[str, Any] = {}
         if extra := json.loads(properties.get("extra")):  # type: ignore
             engine_params = extra.get("engine_params", {})
             connect_args = engine_params.get("connect_args", {})
diff --git a/superset/db_engine_specs/presto.py 
b/superset/db_engine_specs/presto.py
index 3f100a17134..e667a091b94 100644
--- a/superset/db_engine_specs/presto.py
+++ b/superset/db_engine_specs/presto.py
@@ -1235,6 +1235,7 @@ class PrestoEngineSpec(PrestoBaseEngineSpec):
         all_columns: list[ResultSetColumnType] = []
         expanded_columns = []
         current_array_level = None
+        unnested_rows: dict[int, int] = defaultdict(int)
         while to_process:
             column, level = to_process.popleft()
             if column["column_name"] not in [
@@ -1248,7 +1249,7 @@ class PrestoEngineSpec(PrestoBaseEngineSpec):
             # added by the first. every time we change a level in the nested 
arrays
             # we reinitialize this.
             if level != current_array_level:
-                unnested_rows: dict[int, int] = defaultdict(int)
+                unnested_rows = defaultdict(int)
                 current_array_level = level
 
             name = column["column_name"]
diff --git a/tests/unit_tests/common/test_query_context_factory.py 
b/tests/unit_tests/common/test_query_context_factory.py
index 3f092c87694..29ad4c6f609 100644
--- a/tests/unit_tests/common/test_query_context_factory.py
+++ b/tests/unit_tests/common/test_query_context_factory.py
@@ -532,6 +532,42 @@ class TestQueryContextFactory:
 
         assert query_object.columns == ["ds", "other_col"]
 
+    def test_apply_granularity_no_filter_to_remove(self):
+        """No x-axis and no temporal filters leaves the filters untouched."""
+        query_object = Mock(spec=QueryObject)
+        query_object.granularity = "P1D"
+        query_object.columns = ["other_col"]
+        query_object.post_processing = []
+        query_object.filter = [{"col": "other_col", "op": "==", "val": 
"value"}]
+
+        datasource = Mock()
+        datasource.columns = [{"column_name": "ds", "is_dttm": True}]
+
+        self.factory._apply_granularity(query_object, {}, datasource)
+
+        assert query_object.filter == [{"col": "other_col", "op": "==", "val": 
"value"}]
+
+    def test_apply_granularity_with_adhoc_temporal_filter(self):
+        """An adhoc temporal filter is matched on its SQL expression."""
+        adhoc_column = {"label": "ds_expr", "sqlExpression": "DATE(ds)"}
+        query_object = Mock(spec=QueryObject)
+        query_object.granularity = "P1D"
+        query_object.columns = ["other_col"]
+        query_object.post_processing = []
+        query_object.filter = [
+            {"col": adhoc_column, "op": "TEMPORAL_RANGE", "val": "a : b"},
+            {"col": "DATE(ds)", "op": "TEMPORAL_RANGE", "val": "a : b"},
+        ]
+
+        datasource = Mock()
+        datasource.columns = [{"column_name": "ds", "is_dttm": True}]
+
+        self.factory._apply_granularity(query_object, {}, datasource)
+
+        assert query_object.filter == [
+            {"col": adhoc_column, "op": "TEMPORAL_RANGE", "val": "a : b"}
+        ]
+
     def test_apply_filters_with_time_range(self):
         """Test _apply_filters with time_range"""
         query_object = Mock(spec=QueryObject)

Reply via email to