mirror of
https://github.com/apache/superset.git
synced 2026-07-12 09:45:43 +00:00
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
60 lines
2.4 KiB
Python
60 lines
2.4 KiB
Python
# 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 datetime import datetime, timezone
|
|
from unittest.mock import patch
|
|
|
|
from sqlalchemy.orm.session import Session
|
|
|
|
|
|
def test_build_dataset_query_excludes_soft_deleted(session: Session) -> None:
|
|
"""The Core ``select`` in ``build_dataset_query`` must filter
|
|
``deleted_at IS NULL`` explicitly.
|
|
|
|
The ``SoftDeleteMixin`` listener runs on ``do_orm_execute`` only, so it
|
|
never fires for this Core statement — the explicit ``where`` clause is
|
|
the sole thing keeping soft-deleted datasets out of the combined
|
|
datasource list and its pagination counts. This test fails if that
|
|
clause is removed.
|
|
"""
|
|
from superset import db, security_manager
|
|
from superset.connectors.sqla.models import SqlaTable
|
|
from superset.daos.datasource import DatasourceDAO
|
|
from superset.models.core import Database
|
|
|
|
SqlaTable.metadata.create_all(session.get_bind())
|
|
|
|
database = Database(database_name="ds_q_db", sqlalchemy_uri="sqlite://")
|
|
live = SqlaTable(table_name="live_t", schema="main", database=database)
|
|
hidden = SqlaTable(
|
|
table_name="hidden_t",
|
|
schema="main",
|
|
database=database,
|
|
deleted_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
)
|
|
db.session.add_all([database, live, hidden])
|
|
db.session.flush()
|
|
|
|
with patch.object(
|
|
security_manager, "can_access_all_datasources", return_value=True
|
|
):
|
|
query = DatasourceDAO.build_dataset_query(name_filter=None, sql_filter=None)
|
|
# Core execution — exactly the path the ORM listener cannot see.
|
|
names = {row.table_name for row in session.execute(query)}
|
|
|
|
assert "live_t" in names
|
|
assert "hidden_t" not in names
|