Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,14 @@
* specific language governing permissions and limitationsxw
* under the License.
*/
import {
ensureIsArray,
JsonObject,
QueryFormData,
ComparisonType,
} from '@superset-ui/core';
import { ensureIsArray } from '@superset-ui/core';
import type { JsonObject, QueryFormData } from '@superset-ui/core';
import { hasTimeOffset } from './timeOffset';

export const isDerivedSeries = (
series: JsonObject,
formData: QueryFormData,
): boolean => {
const comparisonType = formData.comparison_type;
if (comparisonType !== ComparisonType.Values) {
return false;
}
const timeCompare: string[] = ensureIsArray(formData?.time_compare);
const timeCompare = ensureIsArray(formData?.time_compare).filter((v): v is string => typeof v === 'string');
return hasTimeOffset(series, timeCompare);
};
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const hasTimeOffset = (
timeCompare: string[],
): boolean =>
typeof series.name === 'string'
? !!getTimeOffset(series, timeCompare)
? !!getTimeOffset(series, timeCompare) || timeCompare.includes(series.name)
: false;
Comment on lines 37 to 40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Performance bug: calling getTimeOffset (which scans timeCompare) and then calling timeCompare.includes(...) performs two separate linear scans over timeCompare; compute the offset once and reuse the result to avoid the duplicate O(n) work. [performance]

Severity Level: Minor ⚠️

Suggested change
): boolean =>
typeof series.name === 'string'
? !!getTimeOffset(series, timeCompare)
? !!getTimeOffset(series, timeCompare) || timeCompare.includes(series.name)
: false;
): boolean => {
if (typeof series.name !== 'string') return false;
const foundOffset = getTimeOffset(series, timeCompare);
if (foundOffset) return true;
return Array.isArray(timeCompare) && timeCompare.includes(series.name);
};
Why it matters? ⭐

Calling getTimeOffset (which iterates timeCompare) and then timeCompare.includes(...) results in two linear scans. Caching the result of getTimeOffset and reusing it avoids the duplicate O(n) work with no behavioral change, so this is a valid micro-optimization.

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/timeOffset.ts
**Line:** 37:40
**Comment:**
	*Performance: Performance bug: calling `getTimeOffset` (which scans `timeCompare`) and then calling `timeCompare.includes(...)` performs two separate linear scans over `timeCompare`; compute the offset once and reuse the result to avoid the duplicate O(n) work.

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.


export const getOriginalSeries = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,19 @@ const series = {
data: [100],
};

test('should be false if comparison type is not actual values', () => {
test('should be false if time_compare is not set', () => {
expect(isDerivedSeries(series, formData)).toEqual(false);
Object.keys(ComparisonType)
.filter(type => type === ComparisonType.Values)
.forEach(type => {
const formDataWithComparisonType = {
...formData,
comparison_type: type,
time_compare: ['1 month ago'],
};
expect(isDerivedSeries(series, formDataWithComparisonType)).toEqual(
false,
);
});
});

test('should be true if series name matches time_compare regardless of comparison_type', () => {
Object.values(ComparisonType).forEach(type => {
const formDataWithComparisonType = {
...formData,
comparison_type: type,
time_compare: ['1 month ago'],
};
expect(isDerivedSeries(series, formDataWithComparisonType)).toEqual(true);
});
});

test('should be true if comparison type is values', () => {
Expand Down
Loading