You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2026/07/06 18:41:53 UTC

(superset) branch fix/issue-41795-open-pr created (now 42fd8e19fa7)

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

rusackas pushed a change to branch fix/issue-41795-open-pr
in repository https://gitbox.apache.org/repos/asf/superset.git


      at 42fd8e19fa7 fix(sqla): cast native UUID columns to string for LIKE/ILIKE filters

This branch includes the following new commits:

     new 42fd8e19fa7 fix(sqla): cast native UUID columns to string for LIKE/ILIKE filters

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: fix(sqla): cast native UUID columns to string for LIKE/ILIKE filters

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

rusackas pushed a commit to branch fix/issue-41795-open-pr
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 42fd8e19fa7e65657a0fb93ae69411beff4f9641
Author: Evan <ev...@preset.io>
AuthorDate: Mon Jul 6 11:41:14 2026 -0700

    fix(sqla): cast native UUID columns to string for LIKE/ILIKE filters
    
    Table chart server-pagination search builds an ILIKE filter against the
    searched column. Native UUID columns (PostgreSQL, ClickHouse) map to
    GenericDataType.STRING, so the existing not-a-string guard skipped the
    cast and the raw ILIKE hit the UUID column type, which the database
    rejects (e.g. ClickHouse: "Illegal type UUID of argument of function
    ilike"). Detect UUID native types and force the string cast so
    searching UUID columns works.
    
    Fixes #41795
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
 superset/models/helpers.py              | 24 +++++++++++-
 tests/unit_tests/models/helpers_test.py | 68 +++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/superset/models/helpers.py b/superset/models/helpers.py
index 9ca87780be9..05231369336 100644
--- a/superset/models/helpers.py
+++ b/superset/models/helpers.py
@@ -250,6 +250,18 @@ def json_to_dict(json_str: str) -> dict[Any, Any]:
     return {}
 
 
+def is_uuid_native_type(native_type: Optional[str]) -> bool:
+    """
+    Return True if a native column type represents a UUID.
+
+    Engines such as PostgreSQL and ClickHouse expose native UUID column types
+    (e.g. ``UUID``, ``Nullable(UUID)``) that map to ``GenericDataType.STRING``
+    yet reject LIKE/ILIKE against the raw column, so these columns need an
+    explicit cast to string before pattern matching.
+    """
+    return native_type is not None and "uuid" in native_type.lower()
+
+
 def convert_uuids(obj: Any) -> Any:
     """
     Convert UUID objects to str so we can use yaml.safe_dump
@@ -3746,7 +3758,11 @@ class ExploreMixin:  # pylint: disable=too-many-public-methods
                         utils.FilterOperator.ILIKE,
                         utils.FilterOperator.LIKE,
                     }:
-                        if target_generic_type != GenericDataType.STRING:
+                        # Native UUID columns report GenericDataType.STRING but
+                        # reject LIKE/ILIKE without a cast (see issue #41795)
+                        if target_generic_type != GenericDataType.STRING or (
+                            is_uuid_native_type(col_type)
+                        ):
                             sqla_col = sa.cast(sqla_col, sa.String)
 
                         if op == utils.FilterOperator.LIKE:
@@ -3757,7 +3773,11 @@ class ExploreMixin:  # pylint: disable=too-many-public-methods
                         utils.FilterOperator.NOT_LIKE,
                         utils.FilterOperator.NOT_ILIKE,
                     }:
-                        if target_generic_type != GenericDataType.STRING:
+                        # Native UUID columns report GenericDataType.STRING but
+                        # reject LIKE/ILIKE without a cast (see issue #41795)
+                        if target_generic_type != GenericDataType.STRING or (
+                            is_uuid_native_type(col_type)
+                        ):
                             sqla_col = sa.cast(sqla_col, sa.String)
 
                         if op == utils.FilterOperator.NOT_LIKE:
diff --git a/tests/unit_tests/models/helpers_test.py b/tests/unit_tests/models/helpers_test.py
index 9603e4cd0f5..4993ddc80a8 100644
--- a/tests/unit_tests/models/helpers_test.py
+++ b/tests/unit_tests/models/helpers_test.py
@@ -3410,3 +3410,71 @@ def test_get_sqla_query_dotted_struct_column_bigquery(
     # ```forecasts.original`.`total_cost``` (the regression), so this negative
     # assertion catches the actual failure mode, not just an exact-string match.
     assert "`forecasts.original`" not in sql
+
+
+@pytest.mark.parametrize(
+    "native_type",
+    ["UUID", "uuid", "Nullable(UUID)"],
+)
+@pytest.mark.parametrize(
+    "op",
+    ["LIKE", "ILIKE", "NOT LIKE", "NOT ILIKE"],
+)
+def test_like_filter_on_uuid_column_casts_to_string(
+    database: Database, native_type: str, op: str
+) -> None:
+    """
+    LIKE-family filters on native UUID columns must cast the column to string.
+
+    UUID columns map to ``GenericDataType.STRING``, so the generic-type guard
+    alone skips the string cast — but engines such as PostgreSQL and ClickHouse
+    reject LIKE/ILIKE against a raw UUID column (issue #41795: table chart
+    server-pagination search fails with e.g. "Illegal type UUID of argument of
+    function ilike"). The native column type must force the cast.
+    """
+    from superset.connectors.sqla.models import SqlaTable, TableColumn
+
+    table = SqlaTable(
+        database=database,
+        schema=None,
+        table_name="t",
+        columns=[TableColumn(column_name="event_id", type=native_type)],
+    )
+
+    result = table.get_sqla_query(
+        columns=["event_id"],
+        metrics=[],
+        extras={},
+        filter=[{"col": "event_id", "op": op, "val": "abc%"}],
+        granularity=None,
+        is_timeseries=False,
+        orderby=[],
+    )
+    sql = str(result.sqla_query)
+    assert "CAST" in sql.upper(), f"Expected string cast in SQL: {sql}"
+
+
+def test_like_filter_on_string_column_does_not_cast(database: Database) -> None:
+    """
+    LIKE-family filters on plain string columns must not add a redundant cast.
+    """
+    from superset.connectors.sqla.models import SqlaTable, TableColumn
+
+    table = SqlaTable(
+        database=database,
+        schema=None,
+        table_name="t",
+        columns=[TableColumn(column_name="b", type="TEXT")],
+    )
+
+    result = table.get_sqla_query(
+        columns=["b"],
+        metrics=[],
+        extras={},
+        filter=[{"col": "b", "op": "ILIKE", "val": "abc%"}],
+        granularity=None,
+        is_timeseries=False,
+        orderby=[],
+    )
+    sql = str(result.sqla_query)
+    assert "CAST" not in sql.upper(), f"Unexpected cast in SQL: {sql}"