You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by be...@apache.org on 2026/05/20 00:35:07 UTC

(superset) branch sl-additive-metrics created (now 3c6ae223a2c)

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

betodealmeida pushed a change to branch sl-additive-metrics
in repository https://gitbox.apache.org/repos/asf/superset.git


      at 3c6ae223a2c feat(semantic layers): add metadata on additive metrics

This branch includes the following new commits:

     new 3c6ae223a2c feat(semantic layers): add metadata on additive metrics

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(superset) 01/01: feat(semantic layers): add metadata on additive metrics

Posted by be...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

betodealmeida pushed a commit to branch sl-additive-metrics
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 3c6ae223a2c7e8c70d2d953dd08b330870188dd5
Author: Beto Dealmeida <ro...@dealmeida.net>
AuthorDate: Tue May 19 20:32:50 2026 -0400

    feat(semantic layers): add metadata on additive metrics
---
 .../src/superset_core/semantic_layers/types.py     | 21 ++++++++
 tests/unit_tests/semantic_layers/types_test.py     | 58 ++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/superset-core/src/superset_core/semantic_layers/types.py b/superset-core/src/superset_core/semantic_layers/types.py
index 1239c1303be..3bfa9e8c315 100644
--- a/superset-core/src/superset_core/semantic_layers/types.py
+++ b/superset-core/src/superset_core/semantic_layers/types.py
@@ -92,6 +92,26 @@ class Dimension:
     grain: Grain | None = None
 
 
+class AggregationType(str, enum.Enum):
+    """
+    Aggregation function applied by a metric.
+
+    Additivity (across an arbitrary set of grouping dimensions):
+    * ``SUM``, ``COUNT``: fully additive — sub-group sums roll up via ``sum``.
+    * ``MIN``, ``MAX``: roll up via ``min`` / ``max`` of sub-group values.
+    * ``AVG``, ``COUNT_DISTINCT``, ``OTHER``: not safely roll-uppable from
+      sub-aggregates without auxiliary data.
+    """
+
+    SUM = "SUM"
+    COUNT = "COUNT"
+    MIN = "MIN"
+    MAX = "MAX"
+    AVG = "AVG"
+    COUNT_DISTINCT = "COUNT_DISTINCT"
+    OTHER = "OTHER"
+
+
 @dataclass(frozen=True)
 class Metric:
     id: str
@@ -100,6 +120,7 @@ class Metric:
 
     definition: str
     description: str | None = None
+    aggregation: AggregationType | None = None
 
 
 @dataclass(frozen=True)
diff --git a/tests/unit_tests/semantic_layers/types_test.py b/tests/unit_tests/semantic_layers/types_test.py
new file mode 100644
index 00000000000..0b1e8813f71
--- /dev/null
+++ b/tests/unit_tests/semantic_layers/types_test.py
@@ -0,0 +1,58 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from __future__ import annotations
+
+import pyarrow as pa
+from superset_core.semantic_layers.types import AggregationType, Metric
+
+
+def test_metric_aggregation_defaults_to_none() -> None:
+    metric = Metric(
+        id="x",
+        name="x",
+        type=pa.float64(),
+        definition="sum(x)",
+    )
+    assert metric.aggregation is None
+
+
+def test_metric_accepts_aggregation_type() -> None:
+    metric = Metric(
+        id="x",
+        name="x",
+        type=pa.float64(),
+        definition="sum(x)",
+        aggregation=AggregationType.SUM,
+    )
+    assert metric.aggregation is AggregationType.SUM
+
+
+def test_aggregation_type_is_string_enum() -> None:
+    # Behaves as a string for equality and serialization, so it can be sent
+    # over JSON without an explicit converter.
+    assert AggregationType.SUM == "SUM"
+    assert AggregationType.COUNT_DISTINCT.value == "COUNT_DISTINCT"
+    assert {a.value for a in AggregationType} == {
+        "SUM",
+        "COUNT",
+        "MIN",
+        "MAX",
+        "AVG",
+        "COUNT_DISTINCT",
+        "OTHER",
+    }