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 2025/12/19 00:11:50 UTC
(superset) 01/06: feat(api): add default field to catalogs and schemas API responses
This is an automated email from the ASF dual-hosted git repository.
beto pushed a commit to branch default-db-schema-dropdown
in repository https://gitbox.apache.org/repos/asf/superset.git
commit 4c6df01353a7dca40363cd80d8223bbe4584a202
Author: Beto Dealmeida <ro...@dealmeida.net>
AuthorDate: Thu Dec 18 18:07:22 2025 -0500
feat(api): add default field to catalogs and schemas API responses
Add a `default` field to the `/api/v1/database/{id}/catalogs/` and
`/api/v1/database/{id}/schemas/` endpoints. This field contains the
default catalog/schema for the database, or null if it cannot be
determined or is not accessible to the user.
The default is retrieved from the database engine spec via
`database.get_default_catalog()` and `database.get_default_schema()`.
Error handling ensures the API never fails if default retrieval is slow
or fails - it simply returns null.
RBAC is respected: the default is only returned if the user has access
to it. For the upload_allowed filter, the default is checked against
the allowed schemas list.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <no...@anthropic.com>
---
superset/databases/api.py | 60 +++++++++++++++++++++++++++++++++++++------
superset/databases/schemas.py | 10 ++++++++
2 files changed, 62 insertions(+), 8 deletions(-)
diff --git a/superset/databases/api.py b/superset/databases/api.py
index b0f29c5247..f15391a6df 100644
--- a/superset/databases/api.py
+++ b/superset/databases/api.py
@@ -317,6 +317,32 @@ class DatabaseRestApi(BaseSupersetModelRestApi):
"changed_by": [["id", BaseFilterRelatedUsers, lambda: []]],
}
+ @staticmethod
+ def _get_default_schema(
+ database: Database,
+ catalog: str | None,
+ accessible_schemas: set[str],
+ pk: int,
+ ) -> str | None:
+ """
+ Get the default schema for a database/catalog, with error handling.
+
+ Returns None if the default cannot be determined or is not accessible.
+ """
+ try:
+ default_schema = database.get_default_schema(catalog)
+ # Only include if user has access to it
+ if default_schema and default_schema not in accessible_schemas:
+ return None
+ return default_schema
+ except Exception: # pylint: disable=broad-except
+ logger.debug(
+ "Could not get default schema for database %s, catalog %s",
+ pk,
+ catalog,
+ )
+ return None
+
@expose("/<int:pk>/connection", methods=("GET",))
@protect()
@safe
@@ -726,7 +752,18 @@ class DatabaseRestApi(BaseSupersetModelRestApi):
database,
catalogs,
)
- return self.response(200, result=list(catalogs))
+
+ # Get default catalog with error handling
+ default_catalog = None
+ try:
+ default_catalog = database.get_default_catalog()
+ # Only include if user has access to it
+ if default_catalog and default_catalog not in catalogs:
+ default_catalog = None
+ except Exception: # pylint: disable=broad-except
+ logger.debug("Could not get default catalog for database %s", pk)
+
+ return self.response(200, result=list(catalogs), default=default_catalog)
except OperationalError:
return self.response(
500,
@@ -795,23 +832,30 @@ class DatabaseRestApi(BaseSupersetModelRestApi):
catalog,
schemas,
)
+ default_schema = self._get_default_schema(database, catalog, schemas, pk)
+
if params.get("upload_allowed"):
if not database.allow_file_upload:
- return self.response(200, result=[])
+ return self.response(200, result=[], default=None)
if allowed_schemas := database.get_schema_access_for_file_upload():
# some databases might return the list of schemas in uppercase,
# while the list of allowed schemas is manually inputted so
# could be lowercase
allowed_schemas = {schema.lower() for schema in allowed_schemas}
+ filtered_schemas = [
+ schema
+ for schema in schemas
+ if schema.lower() in allowed_schemas
+ ]
+ # Check if default is in filtered list
+ if default_schema and default_schema.lower() not in allowed_schemas:
+ default_schema = None
return self.response(
200,
- result=[
- schema
- for schema in schemas
- if schema.lower() in allowed_schemas
- ],
+ result=filtered_schemas,
+ default=default_schema,
)
- return self.response(200, result=list(schemas))
+ return self.response(200, result=list(schemas), default=default_schema)
except OperationalError:
return self.response(
500, message="There was an error connecting to the database"
diff --git a/superset/databases/schemas.py b/superset/databases/schemas.py
index 105496efa4..5ca999b15b 100644
--- a/superset/databases/schemas.py
+++ b/superset/databases/schemas.py
@@ -742,12 +742,22 @@ class SchemasResponseSchema(Schema):
result = fields.List(
fields.String(metadata={"description": "A database schema name"})
)
+ default = fields.String(
+ allow_none=True,
+ load_default=None,
+ metadata={"description": "The default schema for this database/catalog"},
+ )
class CatalogsResponseSchema(Schema):
result = fields.List(
fields.String(metadata={"description": "A database catalog name"})
)
+ default = fields.String(
+ allow_none=True,
+ load_default=None,
+ metadata={"description": "The default catalog for this database"},
+ )
class DatabaseTablesResponse(Schema):