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

            Line data    Source code
       1              : import * as dashql from '@ankoh/dashql-core';
       2              : /// No index (u32::MAX)
       3            1 : const NO_INDEX = 0xFFFFFFFF;
       4              : 
       5              : type QueryProfileEvents = dashql.buffers.profile.QueryProfileEvents;
       6              : type ProfileStatsT = dashql.buffers.profile.ProfileStatsT;
       7            1 : const view = dashql.buffers.profile;
       8              : 
       9              : /// The effective state of an entity of a plan (a `ProfileUpdateEvent` of the core)
      10              : export interface ProfileEntityState {
      11              :     readonly status: dashql.buffers.profile.ProfileExecutionStatus;
      12              :     readonly stats: ProfileStatsT;
      13              : }
      14              : 
      15              : /// Is a statistics field known? A field that is not reported is unknown, not 0.
      16            1 : export function isStatReported(stats: ProfileStatsT, field: dashql.buffers.profile.ProfileStatsField): boolean {
      17            1 :     return (stats.reported & field) !== 0;
      18            1 : }
      19              : 
      20              : type States = ReadonlyArray<ProfileEntityState | undefined>;
      21              : 
      22              : /// The execution state of a plan: the effective state of every entity, folded from the output events of the core
      23              : /// query profile (`applyEvents`, `snapshotEvents`). Folding returns a new state, so React can compare states.
      24            1 : export class ProfileExecutionState {
      25            1 :     public static readonly EMPTY = new ProfileExecutionState(null, [], [], [], []);
      26              : 
      27            1 :     public constructor(
      28            1 :         public readonly query: ProfileEntityState | null,
      29            1 :         public readonly fragments: States,
      30            1 :         public readonly pipelines: States,
      31            1 :         public readonly slots: States,
      32            1 :         public readonly operators: States,
      33            1 :     ) {}
      34              : 
      35              :     /// Fold output events into a new state
      36            1 :     public withEvents(events: QueryProfileEvents): ProfileExecutionState {
      37            1 :         if (events.eventsLength() === 0) return this;
      38            1 :         let query = this.query;
      39            1 :         const fragments = [...this.fragments];
      40            1 :         const pipelines = [...this.pipelines];
      41            1 :         const slots = [...this.slots];
      42            1 :         const operators = [...this.operators];
      43            1 :         const event = new view.ProfileUpdateEvent();
      44            1 :         for (let i = 0; i < events.eventsLength(); ++i) {
      45            1 :             events.events(i, event);
      46            1 :             const state: ProfileEntityState = { status: event.status(), stats: event.stats()!.unpack() };
      47            1 :             switch (event.entity()) {
      48            1 :                 case view.ProfileEntity.QUERY: query = state; break;
      49            1 :                 case view.ProfileEntity.FRAGMENT: fragments[event.index()] = state; break;
      50            1 :                 case view.ProfileEntity.PIPELINE: pipelines[event.index()] = state; break;
      51            1 :                 case view.ProfileEntity.SLOT: slots[event.index()] = state; break;
      52            1 :                 case view.ProfileEntity.OPERATOR: operators[event.index()] = state; break;
      53            1 :             }
      54            1 :         }
      55            1 :         return new ProfileExecutionState(query, fragments, pipelines, slots, operators);
      56            1 :     }
      57              : 
      58              :     /// The rows that flowed over an edge: the output of the slot of the child that carries the edge, or the output
      59              :     /// of the child operator if the slot reports none. Null if unknown.
      60            1 :     public edgeRows(slot: number, childOperator: number): bigint | null {
      61            1 :         const reported = (state: ProfileEntityState | undefined) =>
      62            1 :             state != null && isStatReported(state.stats, view.ProfileStatsField.TUPLES_OUT) ? state.stats.tuplesOut : null;
      63            1 :         return (slot !== NO_INDEX ? reported(this.slots[slot]) : null) ?? reported(this.operators[childOperator]);
      64            1 :     }
      65            1 : }
        

Generated by: LCOV version 2.0-1