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

rusackas 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 62ab4cae23d fix(sql-lab): avoid duplicate generated result column 
names (#44189)
62ab4cae23d is described below

commit 62ab4cae23db573f79e72d915f0e1fbb6a20a495
Author: Dennis Khylkouski <[email protected]>
AuthorDate: Fri Oct 2 22:03:18 2026 -0700

    fix(sql-lab): avoid duplicate generated result column names (#44189)
---
 superset/result_set.py              |  7 +++++++
 tests/unit_tests/result_set_test.py | 42 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/superset/result_set.py b/superset/result_set.py
index 2a5de89be4d..3f522963caa 100644
--- a/superset/result_set.py
+++ b/superset/result_set.py
@@ -49,10 +49,17 @@ def dedup(l: list[str], suffix: str = "__", case_sensitive: 
bool = True) -> list
     """
     new_l: list[str] = []
     seen: dict[str, int] = {}
+    reserved = {item if case_sensitive else item.lower() for item in l}
+    fixed_case_suffix = suffix if case_sensitive else suffix.lower()
     for item in l:
         s_fixed_case = item if case_sensitive else item.lower()
         if s_fixed_case in seen:
             seen[s_fixed_case] += 1
+            while (
+                s_fixed_case + fixed_case_suffix + str(seen[s_fixed_case]) in 
reserved
+            ):
+                seen[s_fixed_case] += 1
+            reserved.add(s_fixed_case + fixed_case_suffix + 
str(seen[s_fixed_case]))
             item += suffix + str(seen[s_fixed_case])
         else:
             seen[s_fixed_case] = 0
diff --git a/tests/unit_tests/result_set_test.py 
b/tests/unit_tests/result_set_test.py
index c178d84577a..e1402e54ece 100644
--- a/tests/unit_tests/result_set_test.py
+++ b/tests/unit_tests/result_set_test.py
@@ -28,14 +28,54 @@ from pytest_mock import MockerFixture
 
 from superset.db_engine_specs.base import BaseEngineSpec
 from superset.result_set import (
+    dedup,
     stringify_extension_columns,
     stringify_values,
     SupersetResultSet,
 )
-from superset.superset_typing import DbapiResult
+from superset.superset_typing import DbapiDescription, DbapiResult
 from superset.utils import json as superset_json
 
 
[email protected](
+    "names,case_sensitive,expected",
+    [
+        (["a", "a", "a__1"], True, ["a", "a__2", "a__1"]),
+        (["a__1", "a", "a"], True, ["a__1", "a", "a__2"]),
+        (["a", "a", "a__1", "a__2"], True, ["a", "a__3", "a__1", "a__2"]),
+        (["a", "A", "A__1"], False, ["a", "A__2", "A__1"]),
+        (["a", "A", "A__1"], True, ["a", "A", "A__1"]),
+    ],
+)
+def test_dedup_preserves_explicit_column_names(
+    names: list[str], case_sensitive: bool, expected: list[str]
+) -> None:
+    assert dedup(names, case_sensitive=case_sensitive) == expected
+
+
+def test_result_set_with_colliding_column_suffix() -> None:
+    description: DbapiDescription = [
+        (name, "INT", None, None, None, None, False) for name in ("a", "a", 
"a__1")
+    ]
+    result = SupersetResultSet([(1, 2, 3)], description, BaseEngineSpec)
+    assert result.to_pandas_df().to_dict("records") == [{"a": 1, "a__2": 2, 
"a__1": 3}]
+
+
+def test_dedup_case_insensitive_custom_suffix() -> None:
+    assert dedup(["a", "A", "ax1"], suffix="X", case_sensitive=False) == [
+        "a",
+        "AX2",
+        "ax1",
+    ]
+
+
+def test_dedup_reserves_generated_names() -> None:
+    """Names generated from different bases must not collide."""
+    result = dedup(["a"] * 14 + ["a1"] * 2, suffix="")
+    assert len(set(result)) == len(result)
+    assert result[-1] == "a15"
+
+
 def test_column_names_as_bytes() -> None:
     """
     Test that we can handle column names as bytes.

Reply via email to