apache / superset

Apache Superset is a Data Visualization and Data Exploration Platform
https://superset.apache.org/
Apache License 2.0
62.01k stars 13.59k forks source link

I cannot delete a chart after I deleted the dataset #30428

Open gdudau opened 6 hours ago

gdudau commented 6 hours ago

Bug description

I cannot delete a chart after I deleted the dataset

  1. As Admin I create a chart (Big Number) on specific dataset.
  2. I deleted dataset.
  3. I try to delete chart -> Superset throw error: There was an issue deleting: Big nr chart

When i open this chart there is no name or dataset (see image).

superset_eroare_chart_big_nr

Screenshots/recordings

No response

Superset version

4.0.0

Python version

3.11

Node version

18 or greater

Browser

Firefox

Additional context

DELETE statement on table 'tagged_object' expected to delete 2 row(s); Only 4 were matched.
Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/daos/base.py", line 217, in delete
    db.session.commit()
  File "<string>", line 2, in commit
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 1454, in commit
    self._transaction.commit(_to_root=self.future)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 832, in commit
    self._prepare_impl()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 811, in _prepare_impl
    self.session.flush()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3449, in flush
    self._flush(objects)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3588, in _flush
    with util.safe_reraise():
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
    raise exception
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3549, in _flush
    flush_context.execute()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 456, in execute
    rec.execute(self)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 577, in execute
    self.dependency_processor.process_deletes(uow, states)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/dependency.py", line 1110, in process_deletes
    self._run_crud(
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/dependency.py", line 1207, in _run_crud
    raise exc.StaleDataError(
sqlalchemy.orm.exc.StaleDataError: DELETE statement on table 'tagged_object' expected to delete 2 row(s); Only 4 were matched.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/commands/chart/delete.py", line 49, in run
    ChartDAO.delete(self._models)
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/daos/base.py", line 220, in delete
    raise DAODeleteFailedError(exception=ex) from ex
superset.daos.exceptions.DAODeleteFailedError: Delete failed
2024-09-29 21:42:40,706:ERROR:superset.commands.chart.delete:DELETE statement on table 'tagged_object' expected to delete 2 row(s); Only 4 were matched.
Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/daos/base.py", line 217, in delete
    db.session.commit()
  File "<string>", line 2, in commit
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 1454, in commit
    self._transaction.commit(_to_root=self.future)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 832, in commit
    self._prepare_impl()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 811, in _prepare_impl
    self.session.flush()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3449, in flush
    self._flush(objects)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3588, in _flush
    with util.safe_reraise():
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
    raise exception
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3549, in _flush
    flush_context.execute()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 456, in execute
    rec.execute(self)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 577, in execute
    self.dependency_processor.process_deletes(uow, states)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/dependency.py", line 1110, in process_deletes
    self._run_crud(
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/dependency.py", line 1207, in _run_crud
    raise exc.StaleDataError(
sqlalchemy.orm.exc.StaleDataError: DELETE statement on table 'tagged_object' expected to delete 2 row(s); Only 4 were matched.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/commands/chart/delete.py", line 49, in run
    ChartDAO.delete(self._models)
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/daos/base.py", line 220, in delete
    raise DAODeleteFailedError(exception=ex) from ex
superset.daos.exceptions.DAODeleteFailedError: Delete failed
Error deleting model ChartRestApi: Charts could not be deleted.
Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/daos/base.py", line 217, in delete
    db.session.commit()
  File "<string>", line 2, in commit
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 1454, in commit
    self._transaction.commit(_to_root=self.future)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 832, in commit
    self._prepare_impl()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 811, in _prepare_impl
    self.session.flush()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3449, in flush
    self._flush(objects)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3588, in _flush
    with util.safe_reraise():
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
    raise exception
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3549, in _flush
    flush_context.execute()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 456, in execute
    rec.execute(self)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 577, in execute
    self.dependency_processor.process_deletes(uow, states)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/dependency.py", line 1110, in process_deletes
    self._run_crud(
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/dependency.py", line 1207, in _run_crud
    raise exc.StaleDataError(
sqlalchemy.orm.exc.StaleDataError: DELETE statement on table 'tagged_object' expected to delete 2 row(s); Only 4 were matched.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/commands/chart/delete.py", line 49, in run
    ChartDAO.delete(self._models)
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/daos/base.py", line 220, in delete
    raise DAODeleteFailedError(exception=ex) from ex
superset.daos.exceptions.DAODeleteFailedError: Delete failed

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/charts/api.py", line 460, in delete
    DeleteChartCommand([pk]).run()
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/commands/chart/delete.py", line 52, in run
    raise ChartDeleteFailedError() from ex
superset.commands.chart.exceptions.ChartDeleteFailedError: Charts could not be deleted.
2024-09-29 21:42:40,708:ERROR:superset.charts.api:Error deleting model ChartRestApi: Charts could not be deleted.
Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/daos/base.py", line 217, in delete
    db.session.commit()
  File "<string>", line 2, in commit
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 1454, in commit
    self._transaction.commit(_to_root=self.future)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 832, in commit
    self._prepare_impl()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 811, in _prepare_impl
    self.session.flush()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3449, in flush
    self._flush(objects)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3588, in _flush
    with util.safe_reraise():
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
    raise exception
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/session.py", line 3549, in _flush
    flush_context.execute()
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 456, in execute
    rec.execute(self)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 577, in execute
    self.dependency_processor.process_deletes(uow, states)
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/dependency.py", line 1110, in process_deletes
    self._run_crud(
  File "/home/super/supervenv/lib64/python3.11/site-packages/sqlalchemy/orm/dependency.py", line 1207, in _run_crud
    raise exc.StaleDataError(
sqlalchemy.orm.exc.StaleDataError: DELETE statement on table 'tagged_object' expected to delete 2 row(s); Only 4 were matched.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/commands/chart/delete.py", line 49, in run
    ChartDAO.delete(self._models)
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/daos/base.py", line 220, in delete
    raise DAODeleteFailedError(exception=ex) from ex
superset.daos.exceptions.DAODeleteFailedError: Delete failed

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/charts/api.py", line 460, in delete
    DeleteChartCommand([pk]).run()
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/commands/chart/delete.py", line 52, in run
    raise ChartDeleteFailedError() from ex
superset.commands.chart.exceptions.ChartDeleteFailedError: Charts could not be deleted.
Selenium timed out requesting url http://0.0.0.0:8080/superset/slice/2/?standalone=true
Traceback (most recent call last):
  File "/home/super/supervenv/lib64/python3.11/site-packages/superset/utils/webdriver.py", line 368, in get_screenshot
    element = WebDriverWait(driver, self._screenshot_locate_wait).until(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/super/supervenv/lib64/python3.11/site-packages/selenium/webdriver/support/wait.py", line 95, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: 

Checklist

dosubot[bot] commented 6 hours ago

Hey @gdudau! I'm here to help you with your issue. Let's work together to solve this bug and get everything back on track.

You can't delete a chart after deleting its dataset in Superset version 4.0.2 because the DeleteChartCommand class includes a validation step that checks for the existence of the chart models. If the dataset is deleted, the associated chart models may no longer exist, causing the ChartNotFoundError to be raised during the validation process.

Additionally, when attempting to delete a dataset, Superset provides a warning that the dataset is linked to charts and dashboards, and deleting the dataset will break those objects. This is shown in the DeleteModal component, which lists the affected charts and dashboards and asks for confirmation before proceeding with the deletion.

Here is the relevant code snippet from the DeleteChartCommand class:

def validate(self) -> None:
    # Validate/populate model exists
    self._models = ChartDAO.find_by_ids(self._model_ids)
    if not self._models or len(self._models) != len(self._model_ids):
        raise ChartNotFoundError()
    # Check there are no associated ReportSchedules
    if reports := ReportScheduleDAO.find_by_chart_ids(self._model_ids):
        report_names = [report.name for report in reports]
        raise ChartDeleteFailedReportsExistError(
            _(
                "There are associated alerts or reports: %(report_names)s",
                report_names=",".join(report_names),
            )
        )
    # Check ownership
    for model in self._models:
        try:
            security_manager.raise_for_ownership(model)
        except SupersetSecurityException as ex:
            raise ChartForbiddenError() from ex

The key part is:

self._models = ChartDAO.find_by_ids(self._model_ids)
if not self._models or len(self._models) != len(self._model_ids):
    raise ChartNotFoundError()

This code checks if the chart models exist. If they don't, it raises a ChartNotFoundError, preventing the deletion process from proceeding [1][2].

To continue talking to Dosu, mention @dosu.