예제 #1
0
    def external_metadata_by_name(self, **kwargs: Any) -> FlaskResponse:
        """Gets table metadata from the source system and SQLAlchemy inspector"""
        try:
            params: ExternalMetadataParams = (ExternalMetadataSchema().load(
                kwargs.get("rison")))
        except ValidationError as err:
            return json_error_response(str(err), status=400)

        datasource = ConnectorRegistry.get_datasource_by_name(
            session=db.session,
            datasource_type=params["datasource_type"],
            database_name=params["database_name"],
            schema=params["schema_name"],
            datasource_name=params["table_name"],
        )
        try:
            if datasource is not None:
                # Get columns from Superset metadata
                external_metadata = datasource.external_metadata()
            else:
                # Use the SQLAlchemy inspector to get columns
                database = (db.session.query(Database).filter_by(
                    database_name=params["database_name"]).one())
                external_metadata = get_physical_table_metadata(
                    database=database,
                    table_name=params["table_name"],
                    schema_name=params["schema_name"],
                )
        except (NoResultFound, NoSuchTableError) as ex:
            raise DatasetNotFoundError() from ex
        return self.json_response(external_metadata)
예제 #2
0
    def sync_columns(self) -> None:
        """Sync table columns with the database. Keep metadata for existing columns"""
        try:
            column_metadata = get_physical_table_metadata(
                self.database, self.name, self.schema
            )
        except Exception:  # pylint: disable=broad-except
            column_metadata = []

        existing_columns = {column.name: column for column in self.columns}
        quote_identifier = self.database.quote_identifier

        def update_or_create_column(column_meta: Dict[str, Any]) -> Column:
            column_name: str = column_meta["name"]
            if column_name in existing_columns:
                column = existing_columns[column_name]
            else:
                column = Column(name=column_name)
            column.type = column_meta["type"]
            column.is_temporal = column_meta["is_dttm"]
            column.expression = quote_identifier(column_name)
            column.is_aggregation = False
            column.is_physical = True
            column.is_spatial = False
            column.is_partition = False  # TODO: update with accurate is_partition
            return column

        self.columns = [update_or_create_column(col) for col in column_metadata]
    def external_metadata_by_name(
        self,
        datasource_type: str,
        database_name: str,
        schema_name: str,
        table_name: str,
    ) -> FlaskResponse:
        """Gets table metadata from the source system and SQLAlchemy inspector"""
        database_name = parse_js_uri_path_item(database_name) or ""
        schema_name = parse_js_uri_path_item(schema_name, eval_undefined=True) or ""
        table_name = parse_js_uri_path_item(table_name) or ""

        datasource = ConnectorRegistry.get_datasource_by_name(
            session=db.session,
            datasource_type=datasource_type,
            database_name=database_name,
            schema=schema_name,
            datasource_name=table_name,
        )
        try:
            if datasource is not None:
                external_metadata = datasource.external_metadata()
            else:
                # Use the SQLAlchemy inspector to get columns
                database = (
                    db.session.query(Database)
                    .filter_by(database_name=database_name)
                    .one()
                )
                external_metadata = get_physical_table_metadata(
                    database=database, table_name=table_name, schema_name=schema_name,
                )
        except SupersetException as ex:
            return json_error_response(str(ex), status=400)
        return self.json_response(external_metadata)