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