codeant-ai-for-open-source[bot] commented on code in PR #45071:
URL: https://github.com/apache/superset/pull/45071#discussion_r4224446051


##########
superset/commands/semantic_layer/delete.py:
##########
@@ -32,11 +39,214 @@
 )
 from superset.commands.utils import current_user_can_modify_object
 from superset.daos.semantic_layer import SemanticLayerDAO, SemanticViewDAO
+from superset.dashboards.filters import DashboardAccessFilter
 from superset.exceptions import SupersetSecurityException
+from superset.models.dashboard import Dashboard, dashboard_slices
+from superset.models.slice import Slice
+from superset.reports.filters import ReportScheduleFilter
+from superset.reports.models import ReportSchedule
 from superset.semantic_layers.models import SemanticLayer, SemanticView
+from superset.utils import json
 from superset.utils.decorators import on_error, transaction
 
 logger = logging.getLogger(__name__)
+_DEPENDENT_LIMIT: int = 20
+
+
+def _semantic_target_matches(target: object, view_ids: set[int]) -> bool:
+    """A missing type denotes a table, even when its integer ID collides."""
+    if not isinstance(target, dict) or target.get("datasourceType") != 
"semantic_view":
+        return False
+    raw_id: object = target.get("datasetId")
+    if isinstance(raw_id, bool) or not (
+        isinstance(raw_id, int) or (isinstance(raw_id, str) and 
raw_id.isdecimal())
+    ):
+        return False
+    try:
+        return int(raw_id) in view_ids
+    except ValueError:
+        return False
+
+
+def _dashboard_targets_view(
+    metadata: str, view_ids: set[int], dashboard_id: int
+) -> bool:
+    """Match typed semantic targets in native filters or display controls."""
+    try:
+        decoded: object = json.loads(metadata)
+    except (TypeError, ValueError, RecursionError):
+        logger.debug("Skipping malformed targets on dashboard %s", 
dashboard_id)
+        return False
+    if not isinstance(decoded, dict):
+        logger.debug("Skipping non-object targets on dashboard %s", 
dashboard_id)
+        return False
+    for key in ("native_filter_configuration", "chart_customization_config"):
+        controls: object = decoded.get(key)
+        if not isinstance(controls, list):
+            continue
+        for control in controls:
+            if not isinstance(control, dict):
+                continue
+            targets: object = control.get("targets")
+            if isinstance(targets, list) and any(
+                _semantic_target_matches(target, view_ids) for target in 
targets
+            ):
+                return True
+    return False
+
+
+def _dashboard_target_ids(view_ids: sa.Select) -> set[int]:
+    """Find live dashboards with semantic targets after a coarse SQL 
prefilter."""
+    selected_ids: set[int] = set(db.session.execute(view_ids).scalars())
+    if not selected_ids:
+        return set()
+    candidates: sa.Select = sa.select(Dashboard.id, 
Dashboard.json_metadata).where(
+        Dashboard.deleted_at.is_(None),
+        Dashboard.json_metadata.like("%semantic_view%"),
+    )

Review Comment:
   ✅ **Customized review instruction saved!**
   
   **Instruction:**
   > Do not flag the dashboard metadata scan in semantic-layer deletion: 
native-filter targets exist only in unindexed json_metadata, so the scan is 
necessary and runs only when deleting a semantic source.
   
   **Applied to:**
     - `superset/commands/semantic_layer/delete.py`
   
   ---
   💡 *To manage or update this instruction, visit: [CodeAnt AI 
Settings](https://app.codeant.ai/org/settings/learnings)*



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to