LCOV - code coverage report
Current view: top level - dashql-app/src/views/query_result - visible_rows.ts Coverage Total Hit
Test: DashQL 915828b Lines: 74.5 % 51 38
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as arrow from 'apache-arrow';
       2              : 
       3              : import { TableComputationState } from '../../compute/computation_state.js';
       4              : 
       5              : /// Visit the values of an integer column as numbers, like `Number(column.get(i))` (nulls become 0).
       6              : /// Integer chunks are read from their value buffers directly. A chunk's values are already narrowed
       7              : /// to the chunk's window, so value `i` of the chunk is `values[i]`, exactly what `Vector.get` reads.
       8            1 : export function forEachIntegerValue(column: arrow.Vector, visit: (value: number, index: number) => void): void {
       9            1 :     if (column.type.typeId !== arrow.Type.Int) {
      10            0 :         for (let i = 0; i < column.length; ++i) {
      11            0 :             visit(Number(column.get(i)), i);
      12              :         }
      13            0 :         return;
      14            0 :     }
      15            1 :     let index = 0;
      16            1 :     for (const chunk of column.data) {
      17            1 :         const values = chunk.values as ArrayLike<number | bigint>;
      18            1 :         if (chunk.nullCount === 0) {
      19            1 :             for (let i = 0; i < chunk.length; ++i) {
      20            1 :                 visit(Number(values[i]), index++);
      21              :             }
      22              :         } else {
      23            0 :             for (let i = 0; i < chunk.length; ++i) {
      24            0 :                 visit(chunk.getValid(i) ? Number(values[i]) : 0, index++);
      25              :             }
      26              :         }
      27            1 :     }
      28            1 : }
      29              : 
      30              : /// Resolve the active row-id indirection for a table computation.
      31              : ///
      32              : /// When a cross-filter and/or ordering is active, the compute module produces a
      33              : /// single-column table of row numbers (1-based, from `row_number()`) identifying the
      34              : /// visible rows in display order. Ordering supersedes filtering when both are present
      35              : /// (the ordering task already runs over the filtered subset). Returns `null` when the
      36              : /// full, unfiltered table should be shown.
      37              : ///
      38              : /// The returned array holds 0-based positional indices into the analyzed data table,
      39              : /// ready to gather columns/rows for a renderer.
      40            1 : export function resolveVisibleRowIndices(computation: TableComputationState | null): Int32Array | null {
      41            1 :     if (computation == null) {
      42            0 :         return null;
      43              :     }
      44            1 :     const indirection = computation.orderingTable?.dataTable
      45            1 :         ?? (computation.filterTable == null ? computation.dataSearchTable?.dataTable : computation.filterTable.dataTable)
      46            1 :         ?? null;
      47            1 :     if (indirection == null) {
      48            1 :         return null;
      49              :     }
      50            1 :     if (indirection.numCols !== 1) {
      51            0 :         return null;
      52              :     }
      53            1 :     const column = indirection.getChildAt(0) as arrow.Vector<arrow.Int> | null;
      54            1 :     if (column == null || column.type.typeId !== arrow.Type.Int) {
      55            0 :         return null;
      56              :     }
      57            1 :     const out = new Int32Array(column.length);
      58            1 :     forEachIntegerValue(column, (rowNumber, i) => {
      59              :         // Row numbers are 1-based; convert to a 0-based positional index.
      60            1 :         out[i] = Math.max(rowNumber, 1) - 1;
      61            1 :     });
      62            1 :     return out;
      63            1 : }
      64              : 
      65              : /// Intersect the current cross-filtered/ordered rows with the active Data search.
      66              : /// Search result keys are stable 1-based row numbers from the analyzed data frame.
      67            1 : export function resolveSearchedRowIndices(computation: TableComputationState | null): Int32Array | null {
      68            1 :     if (computation == null || computation.dataSearch.matchingRows == null) {
      69            1 :         return resolveVisibleRowIndices(computation);
      70              :     }
      71            1 :     const visible = computation.orderingTable?.dataSearchRequestId === computation.dataSearchTable?.requestId
      72            1 :         ? resolveVisibleRowIndices(computation)
      73            0 :         : resolveVisibleRowIndices(computation == null ? null : { ...computation, dataSearchTable: null });
      74            1 :     if (visible == null) {
      75            0 :         const rows = Array.from(computation.dataSearch.matchingRows.keys(), rowNumber => rowNumber - 1);
      76            0 :         return Int32Array.from(rows);
      77            0 :     }
      78            1 :     const rows: number[] = [];
      79            1 :     for (const row of visible) {
      80            1 :         if (computation.dataSearch.matchingRows.has(row + 1)) {
      81            1 :             rows.push(row);
      82              :         }
      83              :     }
      84            1 :     return Int32Array.from(rows);
      85            1 : }
        

Generated by: LCOV version 2.0-1