mirror of
https://github.com/apache/superset.git
synced 2024-09-17 11:09:47 -04:00
revisions
This commit is contained in:
parent
a4a7bf9bc9
commit
e36fecdc0b
@ -33,15 +33,11 @@ from superset.models.sql_lab import SavedQuery
|
||||
from superset.queries.saved_queries.commands.bulk_delete import (
|
||||
BulkDeleteSavedQueryCommand,
|
||||
)
|
||||
from superset.queries.saved_queries.commands.create import (
|
||||
CreateSavedQueryCommand
|
||||
)
|
||||
from superset.queries.saved_queries.commands.exceptions import (
|
||||
SavedQueryBulkDeleteFailedError,
|
||||
SavedQueryNotFoundError,
|
||||
SavedQueryImportError,
|
||||
SavedQueryImportError,
|
||||
SavedQueryCreateError,
|
||||
SavedQueryInvalidError,
|
||||
)
|
||||
from superset.queries.saved_queries.commands.export import ExportSavedQueriesCommand
|
||||
@ -71,6 +67,7 @@ class SavedQueryRestApi(BaseSupersetModelRestApi):
|
||||
RouteMethod.EXPORT,
|
||||
RouteMethod.RELATED,
|
||||
RouteMethod.DISTINCT,
|
||||
RouteMethod.IMPORT,
|
||||
"bulk_delete", # not using RouteMethod since locally defined
|
||||
}
|
||||
class_permission_name = "SavedQuery"
|
||||
@ -274,7 +271,7 @@ class SavedQueryRestApi(BaseSupersetModelRestApi):
|
||||
log_to_statsd=False,
|
||||
)
|
||||
def import_(self) -> Response:
|
||||
"""Import chart(s) with associated datasets and databases
|
||||
"""Import Saved Queries with associated datasets and databases
|
||||
---
|
||||
post:
|
||||
requestBody:
|
||||
@ -296,7 +293,7 @@ class SavedQueryRestApi(BaseSupersetModelRestApi):
|
||||
type: bool
|
||||
responses:
|
||||
200:
|
||||
description: Chart import result
|
||||
description: Saved Query import result
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@ -338,62 +335,3 @@ class SavedQueryRestApi(BaseSupersetModelRestApi):
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
logger.exception("Import Saved Query failed")
|
||||
return self.response_500(message=str(exc))
|
||||
@expose("/", methods=["POST"])
|
||||
@protect()
|
||||
@safe
|
||||
@statsd_metrics
|
||||
@event_logger.log_this_with_context(
|
||||
action=lambda self, *args, **kwargs: f"{self.__class__.__name__}.post",
|
||||
log_to_statsd=False,
|
||||
)
|
||||
def post(self) -> Response:
|
||||
"""Creates a new Saved Query
|
||||
---
|
||||
post:
|
||||
description: >-
|
||||
Create a new Saved Query.
|
||||
requestBody:
|
||||
description: Saved Query schema
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/{{self.__class__.__name__}}.post'
|
||||
responses:
|
||||
201:
|
||||
description: Chart added
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: number
|
||||
result:
|
||||
$ref: '#/components/schemas/{{self.__class__.__name__}}.post'
|
||||
400:
|
||||
$ref: '#/components/responses/400'
|
||||
401:
|
||||
$ref: '#/components/responses/401'
|
||||
422:
|
||||
$ref: '#/components/responses/422'
|
||||
500:
|
||||
$ref: '#/components/responses/500'
|
||||
"""
|
||||
if not request.is_json:
|
||||
return self.response_400(message="Request is not JSON")
|
||||
try:
|
||||
item = self.add_model_schema.load(request.json)
|
||||
# This validates custom Schema with custom validations
|
||||
except ValidationError as error:
|
||||
return self.response_400(message=error.messages)
|
||||
try:
|
||||
new_model = CreateSavedQueryCommand(g.user, item).run()
|
||||
return self.response(201, id=new_model.id, result=item)
|
||||
except SavedQueryInvalidError as ex:
|
||||
return self.response_422(message=ex.normalized_messages())
|
||||
except SavedQueryCreateFailedError as ex:
|
||||
logger.error(
|
||||
"Error creating model %s: %s", self.__class__.__name__, str(ex)
|
||||
)
|
||||
return self.response_422(message=str(ex))
|
@ -1,56 +0,0 @@
|
||||
# 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.
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from flask_appbuilder.models.sqla import Model
|
||||
from flask_appbuilder.security.sqla.models import User
|
||||
from marshmallow import ValidationError
|
||||
|
||||
from supereset.queries.saved_queries.commands.exceptions import SavedQueryCreateError, SavedQueryInvalidError
|
||||
from superset.queries.saved_queries.dao import SavedQueryDAO
|
||||
from superset.commands.base import BaseCommand
|
||||
from superset.commands.utils import get_datasource_by_id
|
||||
from superset.dao.exceptions import DAOCreateFailedError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class CreateSavedQueryCommand(BaseCommand):
|
||||
def __init__(self, user: User, data: Dict[str, Any]):
|
||||
self._actor = user
|
||||
self._properties = data.copy()
|
||||
|
||||
def run(self) -> Model:
|
||||
self.validate()
|
||||
try:
|
||||
saved_query = SavedQueryDAO.create(self._properties)
|
||||
except DAOCreateFailedError as ex:
|
||||
logger.exception(ex._exception)
|
||||
raise SavedQueryCreateError
|
||||
return saved_query
|
||||
|
||||
def validate(self) -> None:
|
||||
exceptions = list()
|
||||
datasource_type = self._properties["datasource_type"]
|
||||
datasource_id = self._properties["datasource_id"]
|
||||
owner_ids: Optional[List[int]] = self._properties.get("owners")
|
||||
|
||||
try:
|
||||
datasource = get_datasource_by_id(datasource_id, datasource_type)
|
||||
self._properties["datasource_name"] = datasource.name
|
||||
except ValidationError as ex:
|
||||
exceptions.append(ex)
|
@ -20,7 +20,6 @@ from superset.commands.exceptions import (
|
||||
CommandException,
|
||||
CommandInvalidError,
|
||||
DeleteFailedError,
|
||||
CreateFailedError,
|
||||
ImportFailedError
|
||||
)
|
||||
|
||||
@ -33,11 +32,8 @@ class SavedQueryNotFoundError(CommandException):
|
||||
message = _("Saved query not found.")
|
||||
|
||||
class SavedQueryImportError(ImportFailedError):
|
||||
message = _("Import chart failed for an unknown reason")
|
||||
|
||||
class SavedQueryCreateError(CreateFailedError):
|
||||
message = _("Saved Query could not be created")
|
||||
message = _("Import saved query failed for an unknown reason.")
|
||||
|
||||
class SavedQueryInvalidError(CommandInvalidError):
|
||||
message = _("Saved Query Parameters are invalid")
|
||||
message = _("Saved query parameters are invalid.")
|
||||
|
@ -38,7 +38,7 @@ class ImportSavedQueriesCommand(ImportModelsCommand):
|
||||
prefix ="saved_queries/"
|
||||
schemas: Dict[str, Schema] = {
|
||||
"datasets/": ImportV1DatasetSchema(),
|
||||
"saved_query": ImportV1SavedQuerySchema(),
|
||||
"queries/": ImportV1SavedQuerySchema(),
|
||||
}
|
||||
import_error = SavedQueryImportError
|
||||
|
||||
@ -46,15 +46,10 @@ class ImportSavedQueriesCommand(ImportModelsCommand):
|
||||
def _import(
|
||||
session: Session, configs: Dict[str, Any], overwrite: bool = False
|
||||
) -> None:
|
||||
# discover datasets associated with saved queries
|
||||
dataset_uuids: Set[str] = set()
|
||||
for file_name, config in configs.items():
|
||||
if file_name.startswith("saved_queries/"):
|
||||
dataset_uuids.add(config["dataset_uuid"])
|
||||
# discover databases associated with datasets
|
||||
# discover databases associated with saved queries
|
||||
database_uuids: Set[str] = set()
|
||||
for file_name, config in configs.items():
|
||||
if file_name.startswith("datasets/") and config["uuid"] in dataset_uuids:
|
||||
if file_name.startswith("queries/"):
|
||||
database_uuids.add(config["database_uuid"])
|
||||
|
||||
# import related databases
|
||||
@ -64,27 +59,17 @@ class ImportSavedQueriesCommand(ImportModelsCommand):
|
||||
database = import_database(session, config, overwrite=False)
|
||||
database_ids[str(database.uuid)] = database.id
|
||||
|
||||
# import datasets with the correct parent ref
|
||||
datasets: Dict[str, SqlaTable] = {}
|
||||
for file_name, config in configs.items():
|
||||
if (
|
||||
file_name.startswith("datasets/")
|
||||
and config["database_uuid"] in database_ids
|
||||
):
|
||||
config["database_id"] = database_ids[config["database_uuid"]]
|
||||
dataset = import_dataset(session, config, overwrite=False)
|
||||
datasets[str(dataset.uuid)] = dataset
|
||||
|
||||
# import saved queries with the correct parent ref
|
||||
for file_name, config in configs.items():
|
||||
if file_name.startswith("saved_queries/") and config["dataset_uuid"] in datasets:
|
||||
if file_name.startswith("queries/") and config["database_uuid"] in database:
|
||||
# update datasource id, type, and name
|
||||
dataset = datasets[config["dataset_uuid"]]
|
||||
database = database[config["dataset_uuid"]]
|
||||
config.update(
|
||||
{
|
||||
"datasource_id": dataset.id,
|
||||
"datasource_name": dataset.table_name,
|
||||
"datasource_id": database.id,
|
||||
"datasource_name": database.table_name,
|
||||
}
|
||||
)
|
||||
config["params"].update({"datasource": dataset.uid})
|
||||
config["params"].update({"datasource": database.uid})
|
||||
import_saved_query(session, config, overwrite=overwrite)
|
||||
|
Loading…
Reference in New Issue
Block a user