• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2024 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import m from 'mithril';
16import {SqlValue} from '../../../../trace_processor/query_result';
17import {Trace} from '../../../../public/trace';
18import {SqlColumn, sqlColumnId} from './sql_column';
19import {Filters} from './filters';
20
21// Interface which allows TableColumn to interact with the table (e.g. add filters, or run the query).
22export interface TableManager {
23  filters: Filters;
24  trace: Trace;
25  getSqlQuery(data: {[key: string]: SqlColumn}): string;
26}
27
28export interface TableColumnParams {
29  // See TableColumn.tag.
30  tag?: string;
31  // See TableColumn.alias.
32  alias?: string;
33  // See TableColumn.startsHidden.
34  startsHidden?: boolean;
35}
36
37// Class which represents a column in a table, which can be displayed to the user.
38// It is based on the primary SQL column, but also contains additional information needed for displaying it as a part of a table.
39export interface TableColumn<
40  SupportingColumns extends {[key: string]: SqlColumn} = {},
41> {
42  readonly column: SqlColumn;
43
44  // Column title to be displayed.
45  // If not set, then `alias` will be used if it's unique.
46  // If `alias` is not set as well, then `sqlColumnId(primaryColumn())` will be used.
47  // TODO(altimin): This should return m.Children, but a bunch of things, including low-level widgets (Button, MenuItem, Anchor) need to be fixed first.
48  getTitle?(): string | undefined;
49
50  // In some cases to render a value in a table, we need information from additional columns.
51  // For example, args have three related columns: int_value, string_value and real_value. From the user perspective, we want to coalesce them into a single "value" column,
52  // but to do this correctly we need to fetch the `type` column.
53  supportingColumns?(): SupportingColumns;
54
55  /**
56   * Render a table cell. tableManager can be undefined, in which case the cell should provide basic rendering (e.g. for pivot table).
57   *
58   * @param value The value to be rendered.
59   * @param tableManager Optional table manager to allow interaction with the table (e.g. adding filters).
60   * @param supportingValues Optional additional values needed to render the cell.
61   */
62  renderCell(
63    value: SqlValue,
64    tableManager?: TableManager,
65    supportingValues?: {[key in keyof SupportingColumns]: SqlValue},
66  ): m.Children;
67
68  // A set of columns to be added when opening this table.
69  // It has two primary purposes:
70  // - Allow some columns to be hidden by default (by returning an empty array).
71  // - Expand some columns (e.g. utid and upid are not meaningful by themselves, so the corresponding columns might add a "name" column by default).
72  initialColumns?(): TableColumn[];
73
74  // Some columns / values (arg_set_ids, table ids, etc) are primarily used to reference other data.
75  // This method allows showing the user list of additional columns which can be fetched using this column.
76  listDerivedColumns?(
77    manager: TableManager,
78  ): undefined | (() => Promise<Map<string, TableColumn>>);
79}
80
81// Returns a unique identifier for the table column.
82export function tableColumnId(column: TableColumn): string {
83  return sqlColumnId(column.column);
84}
85
86export function tableColumnAlias(column: TableColumn): string {
87  return tableColumnId(column).replace(/[^a-zA-Z0-9_]/g, '__');
88}
89
90export function columnTitle(column: TableColumn): string {
91  if (column.getTitle !== undefined) {
92    const title = column.getTitle();
93    if (title !== undefined) return title;
94  }
95  return sqlColumnId(column.column);
96}
97