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

betodealmeida pushed a commit to branch oauth-during-db-creation
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 88bc904b3d954df236d8245418089f84fb1d2992
Author: Beto Dealmeida <[email protected]>
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",
+    }

Reply via email to