rusackas commented on code in PR #40907:
URL: https://github.com/apache/superset/pull/40907#discussion_r3976126260


##########
superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx:
##########
@@ -1524,10 +1536,13 @@ export default function TableChart<D extends DataRecord 
= DataRecord>(
       const modifiedOwnState = {
         ...serverPaginationData,
         sortBy,
+        // Changing the sort re-queries the full dataset, so the
+        // previous page offset is meaningless — return to the first page.
+        currentPage: 0,
       };
       updateTableOwnState(setDataMask, modifiedOwnState);
     },
-    [serverPagination, serverPaginationData, setDataMask],
+    [serverPaginationData, setDataMask],
   );

Review Comment:
   Good catch, fixed. Added `serverPagination` back to the dependency array.



##########
superset/charts/data/api.py:
##########
@@ -343,6 +390,16 @@ def data(  # noqa: C901
 
         try:
             query_context = self._create_query_context_from_form(json_body)
+            # Validate sort parameters before executing the query so bad sort
+            # directions are rejected early, before the query builder runs.
+            orderby = (
+                json_body.get("queries", [{}])[0].get("orderby", [])
+                if isinstance(json_body, dict) and json_body.get("queries")
+                else []
+            )
+            sort_error = validate_sort_params(orderby)
+            if sort_error is not None:

Review Comment:
   Fixed, now validates every query object in the request instead of just the 
first.



##########
superset/charts/data/api.py:
##########
@@ -343,6 +390,16 @@ def data(  # noqa: C901
 
         try:
             query_context = self._create_query_context_from_form(json_body)
+            # Validate sort parameters before executing the query so bad sort
+            # directions are rejected early, before the query builder runs.
+            orderby = (
+                json_body.get("queries", [{}])[0].get("orderby", [])
+                if isinstance(json_body, dict) and json_body.get("queries")
+                else []
+            )
+            sort_error = validate_sort_params(orderby)
+            if sort_error is not None:
+                return sort_error

Review Comment:
   Fixed, now validates every query object in the request instead of just the 
first.



##########
superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts:
##########
@@ -128,13 +128,18 @@ const buildQuery: BuildQuery<TableChartFormData> = (
 
     if (queryMode === QueryMode.Aggregate) {
       metrics = metrics || [];
-      // override orderby with timeseries metric when in aggregation mode
-      if (sortByMetric) {
-        orderby = [[sortByMetric, !orderDesc]];
-      } else if (metrics?.length > 0) {
-        // default to ordering by first metric in descending order
-        // when no "sort by" metric is set (regardless if "SORT DESC" is set 
to true)
-        orderby = [[metrics[0], false]];
+      // Fall back to a metric-based default sort only when no explicit orderby
+      // was supplied (e.g. a column sort from the "View as table" results 
pane).
+      // An explicit orderby from form data takes precedence.
+      if (orderby.length === 0) {

Review Comment:
   Good call, but I don't have a working JS test env handy right now to add and 
verify these safely, so I'll leave it as a follow-up rather than push test code 
I can't run.



##########
superset-frontend/plugins/plugin-chart-ag-grid-table/src/buildQuery.ts:
##########
@@ -131,13 +131,18 @@ const buildQuery: BuildQuery<TableChartFormData> = (
 
     if (queryMode === QueryMode.Aggregate) {
       metrics = metrics || [];
-      // override orderby with timeseries metric when in aggregation mode
-      if (sortByMetric) {
-        orderby = [[sortByMetric, !orderDesc]];
-      } else if (metrics?.length > 0) {
-        // default to ordering by first metric in descending order
-        // when no "sort by" metric is set (regardless if "SORT DESC" is set 
to true)
-        orderby = [[metrics[0], false]];
+      // Fall back to a metric-based default sort only when no explicit orderby
+      // was supplied (e.g. a column sort from the "View as table" results 
pane).
+      // An explicit orderby from form data takes precedence.
+      if (orderby.length === 0) {

Review Comment:
   Good call, but I don't have a working JS test env handy right now to add and 
verify these safely, so I'll leave it as a follow-up rather than push test code 
I can't run.



##########
superset-frontend/src/components/GridTable/types.ts:
##########
@@ -59,4 +59,12 @@ export interface TableProps<RecordType> {
   usePagination?: boolean;
 
   striped?: boolean;
+
+  /**
+   * Called when the sort state changes, with it translated to a query
+   * `orderby` (`[[columnId, isAscending]]`) so the consumer can re-request
+   * server-sorted data. Only the primary sort column is included, matching the
+   * chart data API's single-column sort constraint.
+   */

Review Comment:
   Good catch, fixed the docstring to reflect that multi-column sorts pass 
through in priority order.



##########
superset-frontend/src/components/GridTable/types.ts:
##########
@@ -59,4 +59,12 @@ export interface TableProps<RecordType> {
   usePagination?: boolean;
 
   striped?: boolean;
+
+  /**
+   * Called when the sort state changes, with it translated to a query
+   * `orderby` (`[[columnId, isAscending]]`) so the consumer can re-request
+   * server-sorted data. Only the primary sort column is included, matching the
+   * chart data API's single-column sort constraint.
+   */

Review Comment:
   Good catch, fixed the docstring to reflect that multi-column sorts pass 
through in priority order.



##########
superset/views/datasource/schemas.py:
##########
@@ -83,6 +83,22 @@ class SamplesPayloadSchema(Schema):
         metadata={"description": "Extra parameters to add to the query."},
         allow_none=True,
     )
+    orderby = fields.List(
+        fields.Tuple(
+            (
+                fields.Raw(allow_none=False),
+                fields.Boolean(),
+            )
+        ),
+        required=False,
+        allow_none=True,
+        metadata={
+            "description": "Expects a list of lists where the first element is 
the "
+            "column name to sort by, and the second element is a boolean "
+            "(true = ascending).",
+            "example": [("my_col_1", False), ("my_col_2", True)],
+        },

Review Comment:
   Fixed, the example now uses JSON-shaped lists instead of Python tuples.



##########
superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx:
##########
@@ -308,7 +328,10 @@ export default function DrillDetailPane({
   useEffect(() => {
     if (!responseError && !isLoading && !resultsPages.has(pageIndex)) {
       setIsLoading(true);
-      const jsonPayload = getDrillPayload(formData, filters) ?? {};
+      const jsonPayload = {
+        ...getDrillPayload(formData, filters),
+        ...(orderby.length > 0 && { orderby }),
+      };

Review Comment:
   Good catch, fixed with a sort-generation guard so a slower request from 
before the sort change can't land after and overwrite the fresh page cache.



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