diff --git a/superset/app.py b/superset/app.py index e87078836..d40923b25 100644 --- a/superset/app.py +++ b/superset/app.py @@ -158,7 +158,7 @@ class SupersetAppInitializer: Dashboard, DashboardModelViewAsync, ) - from superset.views.database.api import DatabaseRestApi + from superset.databases.api import DatabaseRestApi from superset.views.database.views import ( DatabaseView, CsvToDatabaseView, diff --git a/superset/databases/__init__.py b/superset/databases/__init__.py new file mode 100644 index 000000000..13a83393a --- /dev/null +++ b/superset/databases/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. diff --git a/superset/views/database/api.py b/superset/databases/api.py similarity index 69% rename from superset/views/database/api.py rename to superset/databases/api.py index 2caed02e1..0b8321e70 100644 --- a/superset/views/database/api.py +++ b/superset/databases/api.py @@ -21,13 +21,16 @@ from flask_appbuilder.models.sqla.interface import SQLAInterface from sqlalchemy.exc import NoSuchTableError, SQLAlchemyError from superset import event_logger +from superset.databases.decorators import check_datasource_access +from superset.databases.schemas import ( + SelectStarResponseSchema, + TableMetadataResponseSchema, +) from superset.models.core import Database from superset.typing import FlaskResponse from superset.utils.core import error_msg_from_exception from superset.views.base_api import BaseSupersetModelRestApi -from superset.views.database.decorators import check_datasource_access from superset.views.database.filters import DatabaseFilter -from superset.views.database.mixins import DatabaseMixin from superset.views.database.validators import sqlalchemy_uri_validator @@ -63,9 +66,8 @@ def get_table_metadata( database: Database, table_name: str, schema_name: Optional[str] ) -> Dict[str, Any]: """ - Get table metadata information, including type, pk, fks. - This function raises SQLAlchemyError when a schema is not found. - + Get table metadata information, including type, pk, fks. + This function raises SQLAlchemyError when a schema is not found. :param database: The database model :param table_name: Table name @@ -110,7 +112,7 @@ def get_table_metadata( } -class DatabaseRestApi(DatabaseMixin, BaseSupersetModelRestApi): +class DatabaseRestApi(BaseSupersetModelRestApi): datamodel = SQLAInterface(Database) include_route_methods = {"get_list", "table_metadata", "select_star"} @@ -141,13 +143,15 @@ class DatabaseRestApi(DatabaseMixin, BaseSupersetModelRestApi): "backend", "function_names", ] - show_columns = list_columns - # Removes the local limit for the page size max_page_size = -1 validators_columns = {"sqlalchemy_uri": sqlalchemy_uri_validator} openapi_spec_tag = "Database" + openapi_spec_component_schemas = ( + TableMetadataResponseSchema, + SelectStarResponseSchema, + ) @expose("//table///", methods=["GET"]) @protect() @@ -179,87 +183,11 @@ class DatabaseRestApi(DatabaseMixin, BaseSupersetModelRestApi): description: Table schema responses: 200: - description: Table schema info + description: Table metadata information content: - text/plain: + application/json: schema: - type: object - properties: - columns: - type: array - description: Table columns info - items: - type: object - properties: - keys: - type: array - items: - type: string - longType: - type: string - name: - type: string - type: - type: string - foreignKeys: - type: array - description: Table list of foreign keys - items: - type: object - properties: - column_names: - type: array - items: - type: string - name: - type: string - options: - type: object - referred_columns: - type: array - items: - type: string - referred_schema: - type: string - referred_table: - type: string - type: - type: string - indexes: - type: array - description: Table list of indexes - items: - type: object - properties: - column_names: - type: array - items: - type: string - name: - type: string - options: - type: object - referred_columns: - type: array - items: - type: string - referred_schema: - type: string - referred_table: - type: string - type: - type: string - primaryKey: - type: object - properties: - column_names: - type: array - items: - type: string - name: - type: string - type: - type: string + $ref: "#/components/schemas/TableMetadataResponseSchema" 400: $ref: '#/components/responses/400' 401: @@ -311,15 +239,11 @@ class DatabaseRestApi(DatabaseMixin, BaseSupersetModelRestApi): description: Table schema responses: 200: - description: select star for table + description: SQL statement for a select star for table content: - text/plain: + application/json: schema: - type: object - properties: - result: - type: string - description: SQL select star + $ref: "#/components/schemas/SelectStarResponseSchema" 400: $ref: '#/components/responses/400' 401: diff --git a/superset/views/database/decorators.py b/superset/databases/decorators.py similarity index 100% rename from superset/views/database/decorators.py rename to superset/databases/decorators.py diff --git a/superset/databases/schemas.py b/superset/databases/schemas.py new file mode 100644 index 000000000..8b0a93ee0 --- /dev/null +++ b/superset/databases/schemas.py @@ -0,0 +1,79 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from marshmallow import fields, Schema + + +class TableMetadataOptionsResponseSchema(Schema): + deferrable = fields.Bool() + initially = fields.Bool() + match = fields.Bool() + ondelete = fields.Bool() + onupdate = fields.Bool() + + +class TableMetadataColumnsResponseSchema(Schema): + keys = fields.List(fields.String(), description="") + longType = fields.String(description="The actual backend long type for the column") + name = fields.String(description="The column name") + type = fields.String(description="The column type") + duplicates_constraint = fields.String(required=False) + + +class TableMetadataForeignKeysIndexesResponseSchema(Schema): + column_names = fields.List( + fields.String( + description="A list of column names that compose the foreign key or index" + ) + ) + name = fields.String(description="The name of the foreign key or index") + options = fields.Nested(TableMetadataOptionsResponseSchema) + referred_columns = fields.List(fields.String()) + referred_schema = fields.String() + referred_table = fields.String() + type = fields.String() + + +class TableMetadataPrimaryKeyResponseSchema(Schema): + column_names = fields.List( + fields.String(description="A list of column names that compose the primary key") + ) + name = fields.String(description="The primary key index name") + type = fields.String() + + +class TableMetadataResponseSchema(Schema): + name = fields.String(description="The name of the table") + columns = fields.List( + fields.Nested(TableMetadataColumnsResponseSchema), + description="A list of columns and their metadata", + ) + foreignKeys = fields.List( + fields.Nested(TableMetadataForeignKeysIndexesResponseSchema), + description="A list of foreign keys and their metadata", + ) + indexes = fields.List( + fields.Nested(TableMetadataForeignKeysIndexesResponseSchema), + description="A list of indexes and their metadata", + ) + primaryKey = fields.Nested( + TableMetadataPrimaryKeyResponseSchema, description="Primary keys metadata" + ) + selectStar = fields.String(description="SQL select star") + + +class SelectStarResponseSchema(Schema): + result = fields.String(description="SQL select star")