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/10/13 17:54:35 UTC

(superset) branch sl-oauth2 updated: Encode catalog/schema

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

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


The following commit(s) were added to refs/heads/sl-oauth2 by this push:
     new 6dbc3e64e45 Encode catalog/schema
6dbc3e64e45 is described below

commit 6dbc3e64e45888587b458275d1420bcb28251cb7
Author: Beto Dealmeida <bd...@netflix.com>
AuthorDate: Mon Oct 12 14:21:30 2026 -0400

    Encode catalog/schema
---
 .../src/hooks/apiResources/schemas.test.ts         |  4 +-
 .../src/hooks/apiResources/schemas.ts              |  2 +-
 .../src/hooks/apiResources/tables.test.ts          | 52 ++++++++++++++++++++++
 superset-frontend/src/hooks/apiResources/tables.ts |  5 ++-
 4 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/superset-frontend/src/hooks/apiResources/schemas.test.ts b/superset-frontend/src/hooks/apiResources/schemas.test.ts
index 29ff80c2598..4954a9c6911 100644
--- a/superset-frontend/src/hooks/apiResources/schemas.test.ts
+++ b/superset-frontend/src/hooks/apiResources/schemas.test.ts
@@ -330,10 +330,10 @@ describe('useSchemas hook', () => {
 
   test('returns correct schema list by a catalog', async () => {
     const dbId = '1';
-    const expectCatalog = 'catalog3';
+    const expectCatalog = 'demo%2Emetrics';
     const schemaApiRoute = `glob:*/api/v1/database/*/schemas/*`;
     fetchMock.get(schemaApiRoute, ({ url }) =>
-      url.includes(`catalog:${expectCatalog}`)
+      url.includes(`catalog:demo%252Emetrics`)
         ? fakeApiResult3
         : fakeApiResult2,
     );
diff --git a/superset-frontend/src/hooks/apiResources/schemas.ts b/superset-frontend/src/hooks/apiResources/schemas.ts
index 912023dda69..5f928be7d70 100644
--- a/superset-frontend/src/hooks/apiResources/schemas.ts
+++ b/superset-frontend/src/hooks/apiResources/schemas.ts
@@ -46,7 +46,7 @@ const schemaApi = api.injectEndpoints({
         // TODO: Would be nice to add pagination in a follow-up. Needs endpoint changes.
         urlParams: {
           force: forceRefresh,
-          ...(catalog !== undefined && { catalog }),
+          ...(catalog !== undefined && { catalog: encodeURIComponent(catalog) }),
         },
         transformResponse: ({ json }: JsonResponse) =>
           json.result.sort().map((value: string) => ({
diff --git a/superset-frontend/src/hooks/apiResources/tables.test.ts b/superset-frontend/src/hooks/apiResources/tables.test.ts
index 55fb45d3ccc..ebeeb4b6fc2 100644
--- a/superset-frontend/src/hooks/apiResources/tables.test.ts
+++ b/superset-frontend/src/hooks/apiResources/tables.test.ts
@@ -197,6 +197,58 @@ describe('useTables hook', () => {
     expect(result.current.data).toEqual(expectedHasMoreData);
   });
 
+  test('fetches tables separately for catalogs with the same schema', async () => {
+    const dbId = 'db1';
+    const schema = 'main';
+    const tableApiRoute = `glob:*/api/v1/database/${dbId}/tables/?q=*`;
+    const firstResult = {
+      count: 1,
+      result: [
+        {
+          value: 'demo.metrics.main.download_session',
+          label: 'demo.metrics.main.download_session',
+          type: 'table',
+        },
+      ],
+    };
+    const secondResult = {
+      count: 1,
+      result: [
+        {
+          value: 'shared.main.thumb_report',
+          label: 'shared.main.thumb_report',
+          type: 'table',
+        },
+      ],
+    };
+    fetchMock.get(tableApiRoute, ({ url }) =>
+      url.includes('shared') ? secondResult : firstResult,
+    );
+    fetchMock.get(`glob:*/api/v1/database/${dbId}/schemas/*`, {
+      result: [schema],
+    });
+
+    const { result, rerender } = renderHook(
+      ({ catalog }) => useTables({ dbId, catalog, schema }),
+      {
+        initialProps: { catalog: 'demo%2Emetrics' },
+        wrapper: createWrapper({ useRedux: true, store }),
+      },
+    );
+    await waitFor(() =>
+      expect(result.current.data?.options).toEqual(firstResult.result),
+    );
+    expect(fetchMock.callHistory.calls(tableApiRoute)[0].url).toContain(
+      'demo%252Emetrics',
+    );
+
+    rerender({ catalog: 'shared' });
+    await waitFor(() =>
+      expect(result.current.data?.options).toEqual(secondResult.result),
+    );
+    expect(fetchMock.callHistory.calls(tableApiRoute).length).toBe(2);
+  });
+
   test('returns cached data without api request', async () => {
     const expectDbId = 'db1';
     const expectedSchema = 'schema1';
diff --git a/superset-frontend/src/hooks/apiResources/tables.ts b/superset-frontend/src/hooks/apiResources/tables.ts
index c3c07db9218..9589cee850d 100644
--- a/superset-frontend/src/hooks/apiResources/tables.ts
+++ b/superset-frontend/src/hooks/apiResources/tables.ts
@@ -110,15 +110,16 @@ const tableApi = api.injectEndpoints({
         urlParams: {
           force: forceRefresh,
           schema_name: schema ? encodeURIComponent(schema) : '',
-          ...(catalog && { catalog_name: catalog }),
+          ...(catalog && { catalog_name: encodeURIComponent(catalog) }),
         },
         transformResponse: ({ json }: QueryResponse) => ({
           options: json.result,
           hasMore: json.count > json.result.length,
         }),
       }),
-      serializeQueryArgs: ({ queryArgs: { dbId, schema } }) => ({
+      serializeQueryArgs: ({ queryArgs: { dbId, catalog, schema } }) => ({
         dbId,
+        catalog,
         schema,
       }),
     }),