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


##########
superset-frontend/src/visualizations/TimeTable/utils/sortUtils/sortUtils.ts:
##########
@@ -42,23 +44,45 @@ function compareValues(
 }
 
 /**
- * Sorts table rows with mixed data types for react-table
- * @param rowA - First row to compare
- * @param rowB - Second row to compare
- * @param columnId - Column identifier for sorting
- * @param descending - Whether to sort in descending order
- * @returns Numeric comparison result for react-table
+ * Sorts table rows with mixed data types for react-table.
+ *
+ * react-table handles the asc/desc direction flip internally after calling
+ * this function, so we only return the raw comparison result.
  */
 export function sortNumberWithMixedTypes(
   rowA: any,
   rowB: any,
   columnId: string,
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
   descending: boolean,
 ) {
-  const valueA = rowA.values[columnId].props['data-value'];
-  const valueB = rowB.values[columnId].props['data-value'];
+  const cellA = rowA.values?.[columnId];
+  const cellB = rowB.values?.[columnId];
+
+  // Value cells are React elements created in TimeTable with props:
+  // { valueField, column, reversedEntries }. We can recompute the numeric
+  // value using the same helper that the cell uses.
+  const propsA = cellA?.props as
+    | { valueField: string; column: ColumnConfig; reversedEntries: Entry[] }
+    | undefined;
+  const propsB = cellB?.props as
+    | { valueField: string; column: ColumnConfig; reversedEntries: Entry[] }
+    | undefined;
+
+  if (!propsA || !propsB) {
+    return 0;
+  }
 
-  const comparison = compareValues(valueA, valueB, 'asSmallest');
+  const { value: valueA } = calculateCellValue(
+    propsA.valueField,
+    propsA.column,
+    propsA.reversedEntries,
+  );
+  const { value: valueB } = calculateCellValue(
+    propsB.valueField,
+    propsB.column,
+    propsB.reversedEntries,
+  );

Review Comment:
   **Suggestion:** This comparator assumes every sortable cell has 
`reversedEntries`, but sparkline columns pass `entries` instead. When a 
sparkline column is sorted, `calculateCellValue` receives `undefined` and 
crashes on `reversedEntries.length`. Normalize both cell shapes (ValueCell and 
Sparkline) before calling `calculateCellValue`, and bail out when neither 
provides usable entries. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Sparkline column sorting throws runtime TypeError.
   - ❌ Default initial sort can crash spark-first tables.
   - ⚠️ Sparkline row ordering becomes unusable.
   ```
   </details>
   
   ```suggestion
     const propsA = cellA?.props as
       | {
           valueField: string;
           column: ColumnConfig;
           reversedEntries?: Entry[];
           entries?: Entry[];
         }
       | undefined;
     const propsB = cellB?.props as
       | {
           valueField: string;
           column: ColumnConfig;
           reversedEntries?: Entry[];
           entries?: Entry[];
         }
       | undefined;
   
     const reversedEntriesA =
       propsA?.reversedEntries ?? propsA?.entries?.slice().reverse();
     const reversedEntriesB =
       propsB?.reversedEntries ?? propsB?.entries?.slice().reverse();
   
     if (!propsA || !propsB || !reversedEntriesA || !reversedEntriesB) {
       return 0;
     }
   
     const { value: valueA } = calculateCellValue(
       propsA.valueField,
       propsA.column,
       reversedEntriesA,
     );
     const { value: valueB } = calculateCellValue(
       propsB.valueField,
       propsB.column,
       reversedEntriesB,
     );
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. In Explore, add a Time-series table column with type `spark` (option 
exists in
   
`superset-frontend/src/explore/components/controls/TimeSeriesColumnControl/index.tsx:96-100`).
   
   2. Chart props flow through `transformProps()` and pass `columnCollection` as
   `columnConfigs`
   
(`superset-frontend/src/visualizations/TimeTable/config/transformProps/transformProps.ts:78-83`).
   
   3. `TimeTable` applies `sortType: sortNumberWithMixedTypes` to every 
configured column
   (`superset-frontend/src/visualizations/TimeTable/TimeTable.tsx:54-73`) and 
renders spark
   cells as `<Sparkline ... entries={entries} />` (`TimeTable.tsx:85-93`), so 
spark cell
   props contain `entries` (also defined in 
`components/Sparkline/Sparkline.tsx:28-32`), not
   `reversedEntries`.
   
   4. When sorting runs (header click, or initial sort when `rowType === 
'column'` via
   `TimeTable.tsx:119-127`), `sortNumberWithMixedTypes()` reads
   `propsA.reversedEntries`/`propsB.reversedEntries` and passes `undefined` to
   `calculateCellValue` (`sortUtils.ts:76-85`).
   
   5. `calculateCellValue()` immediately dereferences `reversedEntries.length`
   (`utils/valueCalculations/valueCalculations.ts:147`), causing runtime 
`TypeError` for
   sparkline columns.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/visualizations/TimeTable/utils/sortUtils/sortUtils.ts
   **Line:** 65:85
   **Comment:**
        *Possible Bug: This comparator assumes every sortable cell has 
`reversedEntries`, but sparkline columns pass `entries` instead. When a 
sparkline column is sorted, `calculateCellValue` receives `undefined` and 
crashes on `reversedEntries.length`. Normalize both cell shapes (ValueCell and 
Sparkline) before calling `calculateCellValue`, and bail out when neither 
provides usable entries.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38579&comment_hash=686a45aa486fcd8902fc7aa2363578589b12a15b1f2490818a210b4984ef034c&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38579&comment_hash=686a45aa486fcd8902fc7aa2363578589b12a15b1f2490818a210b4984ef034c&reaction=dislike'>👎</a>



##########
superset-frontend/src/visualizations/TimeTable/utils/sortUtils/sortUtils.test.ts:
##########
@@ -86,7 +77,7 @@ describe('sortNumberWithMixedTypes', () => {
 
     const result = sortNumberWithMixedTypes(rowA, rowB, 'testColumn', false);
 
-    expect(result).toBeLessThan(0);
+    expect(typeof result).toBe('number');

Review Comment:
   **Suggestion:** The string-number test currently only checks that the 
comparator returns a number, which allows incorrect behavior (like returning 
`0` for `'10'` vs `'20'`) to pass. This does not validate actual sorting and 
can hide regressions in mixed-type numeric ordering. Assert the comparison 
direction instead. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ CI may miss TimeTable string-numeric sort regressions.
   - ⚠️ TimeTable header sorting can silently become incorrect.
   ```
   </details>
   
   ```suggestion
       expect(result).toBeLessThan(0);
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open
   
`superset-frontend/src/visualizations/TimeTable/utils/sortUtils/sortUtils.test.ts:74-80`;
   the "should handle string numbers" test compares `'10'` and `'20'` but only 
asserts
   `typeof result === 'number'`.
   
   2. Trace production usage:
   `superset-frontend/src/visualizations/TimeTable/TimeTable.tsx:72` wires
   `sortNumberWithMixedTypes` into `TableView` `sortType`, so comparator 
direction directly
   controls TimeTable column sorting.
   
   3. In 
`superset-frontend/src/visualizations/TimeTable/utils/sortUtils/sortUtils.ts`
   (comparator path at lines `33-43` and return at `87`), any future change 
returning
   `0`/`NaN` for string numerics would still satisfy `typeof result === 
'number'`.
   
   4. Run the unit test suite for this file; the string-number test still 
passes despite
   wrong ordering semantics, so CI can miss a real regression affecting 
header-click sorting
   in TimeTable.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/visualizations/TimeTable/utils/sortUtils/sortUtils.test.ts
   **Line:** 80:80
   **Comment:**
        *Logic Error: The string-number test currently only checks that the 
comparator returns a number, which allows incorrect behavior (like returning 
`0` for `'10'` vs `'20'`) to pass. This does not validate actual sorting and 
can hide regressions in mixed-type numeric ordering. Assert the comparison 
direction instead.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38579&comment_hash=d1a0877be6ca2ea6cc7802361babb4b3f00d0794bdbe95883e5bce50399d38ba&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38579&comment_hash=d1a0877be6ca2ea6cc7802361babb4b3f00d0794bdbe95883e5bce50399d38ba&reaction=dislike'>👎</a>



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