You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by hu...@apache.org on 2020/11/30 17:23:40 UTC

[incubator-superset] branch master updated: feat: Sqllab to Explore UX improvements api changes (#11836)

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

hugh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 0689738  feat: Sqllab to Explore UX improvements api changes (#11836)
0689738 is described below

commit 0689738e7cd1a38d8a905a5ae83e3519169979fa
Author: Hugh A. Miles II <hu...@gmail.com>
AuthorDate: Mon Nov 30 09:23:11 2020 -0800

    feat: Sqllab to Explore UX improvements api changes (#11836)
---
 superset/datasets/api.py             | 14 ++++++++++++-
 superset/datasets/commands/update.py | 32 +++++++++++++++++++++---------
 superset/datasets/dao.py             | 15 ++++++++++++--
 tests/datasets/api_tests.py          | 38 ++++++++++++++++++++++++++++++++++++
 4 files changed, 87 insertions(+), 12 deletions(-)

diff --git a/superset/datasets/api.py b/superset/datasets/api.py
index e5ddae5..7b70031 100644
--- a/superset/datasets/api.py
+++ b/superset/datasets/api.py
@@ -16,6 +16,7 @@
 # under the License.
 import logging
 from datetime import datetime
+from distutils.util import strtobool
 from io import BytesIO
 from typing import Any
 from zipfile import ZipFile
@@ -252,6 +253,10 @@ class DatasetRestApi(BaseSupersetModelRestApi):
             schema:
               type: integer
             name: pk
+          - in: path
+            schema:
+              type: bool
+            name: override_column
           requestBody:
             description: Dataset schema
             required: true
@@ -284,6 +289,11 @@ class DatasetRestApi(BaseSupersetModelRestApi):
             500:
               $ref: '#/components/responses/500'
         """
+        override_columns = (
+            bool(strtobool(request.args["override_columns"]))
+            if "override_columns" in request.args
+            else False
+        )
         if not request.is_json:
             return self.response_400(message="Request is not JSON")
         try:
@@ -292,7 +302,9 @@ class DatasetRestApi(BaseSupersetModelRestApi):
         except ValidationError as error:
             return self.response_400(message=error.messages)
         try:
-            changed_model = UpdateDatasetCommand(g.user, pk, item).run()
+            changed_model = UpdateDatasetCommand(
+                g.user, pk, item, override_columns
+            ).run()
             response = self.response(200, id=changed_model.id, result=item)
         except DatasetNotFoundError:
             response = self.response_404()
diff --git a/superset/datasets/commands/update.py b/superset/datasets/commands/update.py
index dfc3986..7b4c521 100644
--- a/superset/datasets/commands/update.py
+++ b/superset/datasets/commands/update.py
@@ -48,17 +48,29 @@ logger = logging.getLogger(__name__)
 
 
 class UpdateDatasetCommand(BaseCommand):
-    def __init__(self, user: User, model_id: int, data: Dict[str, Any]):
+    def __init__(
+        self,
+        user: User,
+        model_id: int,
+        data: Dict[str, Any],
+        override_columns: bool = False,
+    ):
         self._actor = user
         self._model_id = model_id
         self._properties = data.copy()
         self._model: Optional[SqlaTable] = None
+        self.override_columns = override_columns
 
     def run(self) -> Model:
         self.validate()
         if self._model:
             try:
-                dataset = DatasetDAO.update(self._model, self._properties)
+                dataset = DatasetDAO.update(
+                    model=self._model,
+                    properties=self._properties,
+                    commit=True,
+                    override_columns=self.override_columns,
+                )
                 return dataset
             except DAOUpdateFailedError as ex:
                 logger.exception(ex.exception)
@@ -123,14 +135,16 @@ class UpdateDatasetCommand(BaseCommand):
             ]
             if not DatasetDAO.validate_columns_exist(self._model_id, columns_ids):
                 exceptions.append(DatasetColumnNotFoundValidationError())
+
             # validate new column names uniqueness
-            columns_names: List[str] = [
-                column["column_name"] for column in columns if "id" not in column
-            ]
-            if not DatasetDAO.validate_columns_uniqueness(
-                self._model_id, columns_names
-            ):
-                exceptions.append(DatasetColumnsExistsValidationError())
+            if not self.override_columns:
+                columns_names: List[str] = [
+                    column["column_name"] for column in columns if "id" not in column
+                ]
+                if not DatasetDAO.validate_columns_uniqueness(
+                    self._model_id, columns_names
+                ):
+                    exceptions.append(DatasetColumnsExistsValidationError())
 
     def _validate_metrics(
         self, metrics: List[Dict[str, Any]], exceptions: List[ValidationError]
diff --git a/superset/datasets/dao.py b/superset/datasets/dao.py
index 3b905f4..284a435 100644
--- a/superset/datasets/dao.py
+++ b/superset/datasets/dao.py
@@ -143,8 +143,12 @@ class DatasetDAO(BaseDAO):
         return len(dataset_query) == 0
 
     @classmethod
-    def update(
-        cls, model: SqlaTable, properties: Dict[str, Any], commit: bool = True
+    def update(  # pylint: disable=W:279
+        cls,
+        model: SqlaTable,
+        properties: Dict[str, Any],
+        commit: bool = True,
+        override_columns: bool = False,
     ) -> Optional[SqlaTable]:
         """
         Updates a Dataset model on the metadata DB
@@ -175,6 +179,13 @@ class DatasetDAO(BaseDAO):
                 new_metrics.append(metric_obj)
             properties["metrics"] = new_metrics
 
+        if override_columns:
+            # remove columns initially for full refresh
+            original_properties = properties["columns"]
+            properties["columns"] = []
+            super().update(model, properties, commit=commit)
+            properties["columns"] = original_properties
+
         return super().update(model, properties, commit=commit)
 
     @classmethod
diff --git a/tests/datasets/api_tests.py b/tests/datasets/api_tests.py
index 37ef6a4..bea5fad 100644
--- a/tests/datasets/api_tests.py
+++ b/tests/datasets/api_tests.py
@@ -547,6 +547,44 @@ class TestDatasetApi(SupersetTestCase):
         db.session.delete(dataset)
         db.session.commit()
 
+    def test_update_dataset_item_w_override_columns(self):
+        """
+        Dataset API: Test update dataset with override columns
+        """
+        # Add default dataset
+        dataset = self.insert_default_dataset()
+        self.login(username="admin")
+        dataset_data = {
+            "columns": [
+                {
+                    "column_name": "new_col",
+                    "description": "description",
+                    "expression": "expression",
+                    "type": "INTEGER",
+                    "verbose_name": "New Col",
+                }
+            ],
+            "description": "changed description",
+        }
+        uri = f"api/v1/dataset/{dataset.id}?override_columns=true"
+        rv = self.put_assert_metric(uri, dataset_data, "put")
+        assert rv.status_code == 200
+
+        columns = (
+            db.session.query(TableColumn)
+            .filter_by(table_id=dataset.id)
+            .order_by("column_name")
+            .all()
+        )
+
+        assert columns[0].column_name == dataset_data["columns"][0]["column_name"]
+        assert columns[0].description == dataset_data["columns"][0]["description"]
+        assert columns[0].expression == dataset_data["columns"][0]["expression"]
+        assert columns[0].type == dataset_data["columns"][0]["type"]
+
+        db.session.delete(dataset)
+        db.session.commit()
+
     def test_update_dataset_create_column(self):
         """
         Dataset API: Test update dataset create column