From 6059ef3d83a235ed47f5d81e5663e662e7c9b340 Mon Sep 17 00:00:00 2001 From: Ihor Yeromin Date: Fri, 10 Oct 2025 14:51:45 +0200 Subject: [PATCH] Fix: Sorting with sparse arrays containing empty values (#112114) --- .../src/dataframe/processDataFrame.test.ts | 12 ++++++++++++ .../src/dataframe/processDataFrame.ts | 16 +++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/grafana-data/src/dataframe/processDataFrame.test.ts b/packages/grafana-data/src/dataframe/processDataFrame.test.ts index 72b3041d87c..5c7593e91c0 100644 --- a/packages/grafana-data/src/dataframe/processDataFrame.test.ts +++ b/packages/grafana-data/src/dataframe/processDataFrame.test.ts @@ -365,6 +365,7 @@ describe('sorted DataFrame', () => { { name: 'fourth', type: FieldType.time, values: [1, 2, 3], nanos: [10, 20, 30] }, ], }); + it('Should sort numbers', () => { const sorted = sortDataFrame(frame, 0, true); expect(sorted.length).toEqual(3); @@ -386,6 +387,17 @@ describe('sorted DataFrame', () => { expect(sorted.fields[3].values).toEqual([3, 2, 1]); expect(sorted.fields[3].nanos).toEqual([30, 20, 10]); }); + + it('Should handle arrays with empty values correctly', () => { + // Create a sparse array with empty slots (undefined values) + const values = ['502', '502', , '500', '500', '200', '404']; // Note the empty slot at index 2 + const frame = toDataFrame({ + fields: [{ name: 'status', type: FieldType.string, values }], + }); + const sorted = sortDataFrame(frame, 0, false); + + expect(sorted.fields[0].values).toEqual(['200', '404', '500', '500', '502', '502', undefined]); + }); }); describe('sorted DataFrame by nanos', () => { diff --git a/packages/grafana-data/src/dataframe/processDataFrame.ts b/packages/grafana-data/src/dataframe/processDataFrame.ts index 4a028b6b4fd..14621547725 100644 --- a/packages/grafana-data/src/dataframe/processDataFrame.ts +++ b/packages/grafana-data/src/dataframe/processDataFrame.ts @@ -429,18 +429,20 @@ export function sortDataFrame(data: DataFrame, sortIndex?: number, reverse = fal return { ...data, - fields: data.fields.map((f) => { - const newF = { - ...f, - values: f.values.map((v, i) => f.values[index[i]]), + fields: data.fields.map((field) => { + const newValues = Array.from({ length: field.values.length }, (_, i) => field.values[index[i]]); + + const newField = { + ...field, + values: newValues, }; // only add .nanos if it exists - const { nanos } = f; + const { nanos } = field; if (nanos !== undefined) { - newF.nanos = nanos.map((n, i) => nanos[index[i]]); + newField.nanos = Array.from({ length: nanos.length }, (_, i) => nanos[index[i]]); } - return newF; + return newField; }), }; }