You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by di...@apache.org on 2026/08/25 16:26:55 UTC

(superset) 01/01: fix(dashboard): resolve metric Label in Chart Data (View as table) results grid

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

geido pushed a commit to branch sc-115797
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 46a856a4d67ef3ea0c4de2a908697989340ae7a8
Author: geido <di...@gmail.com>
AuthorDate: Tue Aug 25 16:26:40 2026 +0000

    fix(dashboard): resolve metric Label in Chart Data (View as table) results grid
    
    The dataset drill_info endpoint used to build the results-grid
    verbose_map only ever selected/serialized a dataset's columns, never
    its metrics. SavedMetric verbose_name (Label) was therefore always
    dropped, so a metric's technical name (e.g. sum__num) fell through to
    the "View as table" column header even though the chart itself showed
    the friendly Label correctly.
    
    Adds metrics.metric_name/verbose_name to the drill_info select columns
    and DatasetDrillInfoSchema so the frontend's existing createVerboseMap
    logic (which already merges metrics into verbose_map) has data to work
    with.
    
    SC-115797
---
 superset/datasets/api.py                      |  2 ++
 superset/datasets/schemas.py                  | 15 +++++++++++++-
 tests/integration_tests/datasets/api_tests.py | 28 +++++++++++++++++++++++++++
 3 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/superset/datasets/api.py b/superset/datasets/api.py
index 1fc7634b8b3..e429cf3c35b 100644
--- a/superset/datasets/api.py
+++ b/superset/datasets/api.py
@@ -1757,6 +1757,8 @@ class DatasetRestApi(SoftDeleteApiMixin, BaseSupersetModelRestApi):
             "columns.column_name",
             "columns.verbose_name",
             "columns.groupby",
+            "metrics.metric_name",
+            "metrics.verbose_name",
         ]
         dataset_schema = DatasetDrillInfoSchema()
 
diff --git a/superset/datasets/schemas.py b/superset/datasets/schemas.py
index 59aa2185c78..a5b62714d89 100644
--- a/superset/datasets/schemas.py
+++ b/superset/datasets/schemas.py
@@ -479,6 +479,11 @@ class DatasetColumnDrillInfoSchema(Schema):
     verbose_name = fields.String(required=False)
 
 
+class DatasetMetricDrillInfoSchema(Schema):
+    metric_name = fields.String(required=True)
+    verbose_name = fields.String(required=False)
+
+
 class UserSchema(Schema):
     first_name = fields.String()
     last_name = fields.String()
@@ -488,6 +493,7 @@ class UserSchema(Schema):
 class DatasetDrillInfoSchema(Schema):
     id = fields.Integer()
     columns = fields.List(fields.Nested(DatasetColumnDrillInfoSchema))
+    metrics = fields.List(fields.Nested(DatasetMetricDrillInfoSchema))
     table_name = fields.String()
     editors = fields.List(fields.Nested(SubjectResponseSchema))
     created_by = fields.Nested(UserSchema)
@@ -503,6 +509,9 @@ class DatasetDrillInfoSchema(Schema):
         """
         Clear API response to avoid exposing sensitive information for embedded users,
         and filter columns to only include those with groupby=True for drill operations.
+        Metrics are passed through unfiltered since they are used to resolve display
+        labels (e.g. for the dashboard "View as table" results grid) rather than for
+        drill-by dimension selection.
         """
         dimensions = {
             col.column_name
@@ -516,5 +525,9 @@ class DatasetDrillInfoSchema(Schema):
         ]
 
         if security_manager.is_guest_user():
-            return {"id": serialized["id"], "columns": serialized["columns"]}
+            return {
+                "id": serialized["id"],
+                "columns": serialized["columns"],
+                "metrics": serialized.get("metrics", []),
+            }
         return serialized
diff --git a/tests/integration_tests/datasets/api_tests.py b/tests/integration_tests/datasets/api_tests.py
index 56f3e38efd7..5fb868b5a4b 100644
--- a/tests/integration_tests/datasets/api_tests.py
+++ b/tests/integration_tests/datasets/api_tests.py
@@ -3375,6 +3375,17 @@ class TestDatasetApi(SupersetTestCase):
                     groupby=False,
                 ),
             ],
+            metrics=[
+                SqlMetric(
+                    metric_name="sum__value",
+                    expression="SUM(value)",
+                    verbose_name="Yearly Total",
+                ),
+                SqlMetric(
+                    metric_name="count",
+                    expression="COUNT(*)",
+                ),
+            ],
             fetch_metadata=False,
         )
 
@@ -3399,6 +3410,13 @@ class TestDatasetApi(SupersetTestCase):
             {"column_name": "category", "verbose_name": "Category Column"},
             {"column_name": "region", "verbose_name": None},
         ]
+        # Metrics must also carry their verbose_name so that consumers (e.g.
+        # the dashboard "View as table" results grid) can resolve a metric's
+        # friendly Label instead of falling back to its technical name.
+        assert result["metrics"] == [
+            {"metric_name": "sum__value", "verbose_name": "Yearly Total"},
+            {"metric_name": "count", "verbose_name": None},
+        ]
 
         self.items_to_delete = [dataset]
 
@@ -3509,6 +3527,13 @@ class TestDatasetApi(SupersetTestCase):
                     groupby=True,
                 ),
             ],
+            metrics=[
+                SqlMetric(
+                    metric_name="sum__value",
+                    expression="SUM(value)",
+                    verbose_name="Yearly Total",
+                ),
+            ],
             fetch_metadata=False,
         )
         chart = self.insert_chart("Test Embedded Chart", dataset.id)
@@ -3535,6 +3560,9 @@ class TestDatasetApi(SupersetTestCase):
                     {"column_name": "category", "verbose_name": "Category Column"},
                     {"column_name": "region", "verbose_name": None},
                 ],
+                "metrics": [
+                    {"metric_name": "sum__value", "verbose_name": "Yearly Total"},
+                ],
             }
 
         self.items_to_delete = [dash, chart, dataset]