EnxDev commented on code in PR #44082:
URL: https://github.com/apache/superset/pull/44082#discussion_r4045112910


##########
superset/dashboards/excel_export/sync_budget.py:
##########
@@ -0,0 +1,107 @@
+# 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.
+"""Plan and size dashboard Excel exports served in the HTTP response."""
+
+from __future__ import annotations
+
+import logging
+from dataclasses import dataclass
+from typing import Any
+
+from celery.exceptions import SoftTimeLimitExceeded
+from flask import current_app
+
+from superset.dashboards.excel_export.layout import get_charts_in_layout_order
+from superset.dashboards.excel_export.workbook import (
+    resolve_query_context,
+    ResolvedQueryContexts,
+)
+
+logger = logging.getLogger(__name__)
+
+
+@dataclass(frozen=True)
+class InlineExportPlan:
+    """Queries planned for a direct download and their row budget."""
+
+    #: Resolved query contexts by chart id. ``None`` marks a skipped chart.
+    query_contexts: ResolvedQueryContexts
+    #: Combined row limit, or ``None`` when any query has no finite limit.
+    requested_rows: int | None
+    #: Configured limit for direct downloads.
+    max_rows: int
+
+    @property
+    def fits_row_budget(self) -> bool:
+        """Return whether the export can run during the request."""
+        return self.requested_rows is not None and self.requested_rows <= 
self.max_rows
+
+
+def _finite_row_limit(query: Any) -> int | None:
+    """Return a safe upper bound for one query's result rows."""
+    if not isinstance(query, dict):
+        return None
+    # Grouping sets do not apply row_limit and may fan out into several 
queries.
+    if query.get("grouping_sets"):
+        return None
+    columns = query.get("columns")
+    metrics = query.get("metrics")
+    if (
+        columns == []
+        and isinstance(metrics, list)
+        and metrics
+        and not query.get("is_timeseries")
+    ):
+        # A metric query with no grouping columns returns one aggregate row.
+        return 1
+    row_limit = query.get("row_limit") or current_app.config["ROW_LIMIT"]
+    if isinstance(row_limit, bool) or not isinstance(row_limit, int):

Review Comment:
   You are right — `ChartDataQueryContextSchema.row_limit` is a non-strict 
`fields.Integer`, so the execution path coerces `"1000"` (and `1000.0`) while 
the planner refused the whole dashboard. Planning now reads the limit the same 
way, through a coercion that mirrors the field: every value `int()` converts is 
accepted, and only a value the schema itself would reject (negative, 
non-numeric, non-scalar) leaves the query unbounded. Covered by unit tests for 
both the accepted and rejected forms. Fixed in 8db370e6b5.



-- 
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