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

hainenber 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 958d1ab256a test(rls): assert dataset search returns all mask matches 
(#29707) (#41968)
958d1ab256a is described below

commit 958d1ab256a84e171cbf02761538e5c61c39eeda
Author: Evan Rusackas <[email protected]>
AuthorDate: Sun Jul 12 06:23:29 2026 -0700

    test(rls): assert dataset search returns all mask matches (#29707) (#41968)
    
    Co-authored-by: Claude Code <[email protected]>
---
 .../security/row_level_security_tests.py           | 56 ++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/tests/integration_tests/security/row_level_security_tests.py 
b/tests/integration_tests/security/row_level_security_tests.py
index ac5fbce4453..a3f2c394152 100644
--- a/tests/integration_tests/security/row_level_security_tests.py
+++ b/tests/integration_tests/security/row_level_security_tests.py
@@ -469,6 +469,62 @@ class TestRowLevelSecurityWithRelatedAPI(SupersetTestCase):
         assert all("birth" in table_name.lower() for table_name in 
received_tables)
         assert len(result) >= 1  # At least birth_names should be returned
 
+    @pytest.mark.usefixtures("load_birth_names_data")
+    def test_rls_tables_related_api_returns_all_masked_matches(self):
+        """
+        Regression for #29707: the RLS dataset selector's async search must
+        return *every* dataset whose name matches the typed mask, not a
+        truncated subset. The reporter had two "birth" datasets (birth_names
+        and birth_france_by_region) and searching "birth" showed an
+        incomplete list. This exercises the backend ``related/tables``
+        endpoint that feeds that selector to prove whether the search-by-mask
+        lookup is the culprit.
+        """
+        self.login(ADMIN_USERNAME)
+
+        birth_names = self.get_table(name="birth_names")
+        # Create a sibling dataset whose name also contains the "birth" mask,
+        # mirroring the two-dataset scenario from the issue.
+        sibling = SqlaTable(
+            table_name="birth_france_by_region",
+            database=birth_names.database,
+            schema=birth_names.schema,
+        )
+        db.session.add(sibling)
+        db.session.commit()
+
+        try:
+            # Datasets in the metadata DB that match the "birth" mask. Keep a
+            # sorted list rather than a set so datasets that render the same
+            # display name (same table/schema across databases) are not
+            # collapsed, which would let the multiplicity disagree with the
+            # API's row count below.
+            expected = sorted(
+                t.name
+                for t in db.session.query(SqlaTable)
+                .filter(SqlaTable.table_name.ilike("%birth%"))
+                .all()
+            )
+            # Both datasets must be present in the ground truth for the
+            # assertion below to be meaningful.
+            bare_names = {name.split(".")[-1] for name in expected}
+            assert "birth_names" in bare_names
+            assert "birth_france_by_region" in bare_names
+
+            params = rison.dumps({"filter": "birth", "page": 0, "page_size": 
100})
+            rv = 
self.client.get(f"/api/v1/rowlevelsecurity/related/tables?q={params}")
+            assert rv.status_code == 200
+            data = json.loads(rv.data.decode("utf-8"))
+            received = sorted(table["text"] for table in data["result"])
+
+            # The masked search must return *all* matching datasets (preserving
+            # multiplicity), and the advertised count must not under-report 
them.
+            assert received == expected
+            assert data["count"] == len(expected)
+        finally:
+            db.session.delete(sibling)
+            db.session.commit()
+
     def test_rls_tables_related_api_with_filter_no_matches(self):
         self.login(ADMIN_USERNAME)
         # Test with filter that should match nothing

Reply via email to