LCOV - code coverage report
Current view: top level - dashql-app/src/views/query_profile - profile_navigation.ts Coverage Total Hit
Test: DashQL 915828b Lines: 97.6 % 41 40
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import type { ProfileSceneEdge, ProfileSceneOperator } from './profile_scene.js';
       2              : 
       3              : export type ProfileNavigationDirection = 'left' | 'right' | 'up' | 'down';
       4              : 
       5              : /// Find the operator in a direction of an operator.
       6              : /// The inputs of an operator are below it, or right of it if the plan grows left-to-right. The other two directions
       7              : /// step through the operators of a level (a row, or a column if the plan grows left-to-right).
       8            1 : export function findProfileOperatorInDirection(
       9            1 :     operators: readonly ProfileSceneOperator[],
      10            1 :     edges: readonly Pick<ProfileSceneEdge, 'childOperator' | 'parentOperator'>[],
      11            1 :     current: ProfileSceneOperator | null,
      12            1 :     direction: ProfileNavigationDirection,
      13            1 :     leftToRight = false,
      14            1 : ): ProfileSceneOperator | null {
      15            1 :     if (operators.length === 0) return null;
      16            1 :     if (current == null) {
      17            1 :         const sign = direction === 'left' || direction === 'up' ? -1 : 1;
      18            1 :         const coordinate = direction === 'left' || direction === 'right' ? 'x' : 'y';
      19            1 :         return [...operators].sort((left, right) =>
      20            1 :             sign * (left.rect[coordinate] - right.rect[coordinate]) || left.id - right.id,
      21            1 :         )[0];
      22            1 :     }
      23              : 
      24            1 :     const toChild = leftToRight ? 'right' : 'down';
      25            1 :     const toParent = leftToRight ? 'left' : 'up';
      26            1 :     if (direction === toChild) {
      27            1 :         const child = edges.find(edge => edge.parentOperator === current.id)?.childOperator;
      28            1 :         return child == null ? null : operators.find(operator => operator.id === child) ?? null;
      29            1 :     }
      30            1 :     if (direction === toParent) {
      31            1 :         const parent = edges.find(edge => edge.childOperator === current.id)?.parentOperator;
      32            1 :         return parent == null ? null : operators.find(operator => operator.id === parent) ?? null;
      33            1 :     }
      34              : 
      35              :     // The operators of a level share their y, or the left edge of their column if the plan grows left-to-right
      36            1 :     const level = (operator: ProfileSceneOperator) => leftToRight ? operator.rect.x - operator.rect.width / 2 : operator.rect.y;
      37            1 :     const position = (operator: ProfileSceneOperator) => leftToRight ? operator.rect.y : operator.rect.x;
      38            1 :     const backwards = direction === 'left' || direction === 'up';
      39            1 :     const candidates = operators.flatMap(operator => {
      40            1 :         if (operator.id === current.id) return [];
      41            1 :         const delta = position(operator) - position(current);
      42            1 :         if (level(operator) !== level(current)) return [];
      43            1 :         if (backwards ? delta >= 0 : delta <= 0) return [];
      44            1 :         return [{ operator, distance: Math.abs(delta) }];
      45            1 :     });
      46            1 :     candidates.sort((left, right) =>
      47            1 :         left.distance - right.distance
      48            0 :         || left.operator.id - right.operator.id,
      49            1 :     );
      50            1 :     return candidates[0]?.operator ?? null;
      51            1 : }
        

Generated by: LCOV version 2.0-1