LCOV - code coverage report
Current view: top level - dashql-app/src/compute/tasks - table_ordering.ts Coverage Total Hit
Test: DashQL 915828b Lines: 71.2 % 52 37
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import { DataFrame, generateTableName } from '../data_frame.js';
       2              : import { TableOrderingTask, OrderingTable } from '../computation_types.js';
       3              : import { LoggableException, LoggerLike, stringifyError } from '../../platform/logger/logger.js';
       4              : import { SQLFrame } from '../sql/sqlframe_builder.js';
       5              : import { ComputeQueryExecution, executeDirectly } from '../computation_tasks.js';
       6              : 
       7            1 : const LOG_CTX = "compute";
       8              : 
       9            1 : export async function sortTable(task: TableOrderingTask, logger: LoggerLike, executeQuery: ComputeQueryExecution = executeDirectly): Promise<OrderingTable> {
      10            1 :     if (task.orderingConstraints.length == 1) {
      11            1 :         logger.info("Sorting table by field", {
      12            1 :             "field": task.orderingConstraints[0].field
      13            1 :         }, LOG_CTX);
      14              :     } else {
      15            0 :         logger.info("Sorting table by multiple fields", {}, LOG_CTX);
      16              :     }
      17              : 
      18            1 :     try {
      19            1 :         let frame = SQLFrame.from(task.inputDataFrame.tableName);
      20            1 :         if (task.filterTable != null) {
      21            0 :             frame = frame.semiJoinFilter(
      22            0 :                 task.rowNumberColumnName,
      23            0 :                 task.filterTable.dataFrame.tableName,
      24            0 :                 task.filterTable.dataTable.schema.fields[0].name,
      25            0 :             );
      26              :         }
      27            1 :         if (task.dataSearchTable != null) {
      28            0 :             frame = frame.semiJoinFilter(
      29            0 :                 task.rowNumberColumnName,
      30            0 :                 task.dataSearchTable.dataFrame.tableName,
      31            0 :                 task.dataSearchTable.dataTable.schema.fields[0].name,
      32            0 :             );
      33              :         }
      34              :         // The table keeps the fields of the ordering, the read sorts the rows. Equal rows keep the order of the input.
      35            1 :         const fields = new Set([task.rowNumberColumnName, ...task.orderingConstraints.map(constraint => constraint.field)]);
      36            1 :         const sql = frame
      37            1 :             .project([...fields])
      38            1 :             .toSQL();
      39              : 
      40            1 :         const sortStart = performance.now();
      41            1 :         const tableName = generateTableName("__ordered");
      42            1 :         const transformed = await executeQuery(sql, clientContext => DataFrame.fromSQL(task.inputDataFrame.database, sql, tableName, undefined, clientContext));
      43            1 :         const orderedTable = await transformed.readTable({
      44            1 :             orderBy: [...task.orderingConstraints, { field: task.rowNumberColumnName }],
      45            1 :             columns: [task.rowNumberColumnName],
      46            1 :         });
      47            1 :         const sortEnd = performance.now();
      48            1 :         logger.info("Sorted table", {
      49            1 :             "version": task.tableVersion.toString(),
      50            1 :             "duration": Math.floor(sortEnd - sortStart).toString(),
      51            1 :             "inputRows": task.inputDataTable.numRows.toString(),
      52            1 :             "outputRows": orderedTable.numRows.toString(),
      53            1 :         }, LOG_CTX);
      54              :         const out: OrderingTable = {
      55            1 :             inputRowNumberColumnName: task.rowNumberColumnName,
      56            1 :             orderingConstraints: task.orderingConstraints,
      57            1 :             dataTable: orderedTable,
      58            1 :             dataFrame: transformed,
      59              :             // Ordering depends on filtered data, so version stays same
      60            1 :             version: task.tableVersion,
      61            1 :             dataSearchRequestId: task.dataSearchTable?.requestId ?? null,
      62              :         };
      63            1 :         return out;
      64              : 
      65            1 :     } catch (error: any) {
      66            0 :         if (error instanceof LoggableException) {
      67            0 :             throw error;
      68              :         } else {
      69            0 :             throw new LoggableException(`Sorting table failed`, { "error": stringifyError(error) }, LOG_CTX);
      70              :         }
      71            0 :     }
      72            1 : }
        

Generated by: LCOV version 2.0-1