• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2023 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';
16
17import {raf} from '../../core/raf_scheduler';
18import {Engine} from '../../trace_processor/engine';
19import {STR} from '../../trace_processor/query_result';
20import {
21  constraintsToQueryPrefix,
22  constraintsToQuerySuffix,
23  SQLConstraints,
24} from '../../trace_processor/sql_utils';
25import {FilterableSelect} from '../../widgets/select';
26import {Spinner} from '../../widgets/spinner';
27
28import {argColumn} from './column';
29import {ArgSetIdColumn} from './table_description';
30
31const MAX_ARGS_TO_DISPLAY = 15;
32
33interface ArgumentSelectorAttrs {
34  engine: Engine;
35  argSetId: ArgSetIdColumn;
36  tableName: string;
37  constraints: SQLConstraints;
38  // List of aliases for existing columns by the table.
39  alreadySelectedColumns: Set<string>;
40  onArgumentSelected: (argument: string) => void;
41}
42
43// A widget which allows the user to select a new argument to display.
44// Dinamically queries Trace Processor to find the relevant set of arg_set_ids
45// and which args are present in these arg sets.
46export class ArgumentSelector
47  implements m.ClassComponent<ArgumentSelectorAttrs>
48{
49  argList?: string[];
50
51  constructor({attrs}: m.Vnode<ArgumentSelectorAttrs>) {
52    this.load(attrs);
53  }
54
55  private async load(attrs: ArgumentSelectorAttrs) {
56    const queryResult = await attrs.engine.query(`
57      -- Encapsulate the query in a CTE to avoid clashes between filters
58      -- and columns of the 'args' table.
59      WITH arg_sets AS (
60        ${constraintsToQueryPrefix(attrs.constraints)}
61        SELECT DISTINCT ${attrs.tableName}.${attrs.argSetId.name} as arg_set_id
62        FROM ${attrs.tableName}
63        ${constraintsToQuerySuffix(attrs.constraints)}
64      )
65      SELECT
66        DISTINCT args.key as key
67      FROM arg_sets
68      JOIN args USING (arg_set_id)
69    `);
70    this.argList = [];
71    const it = queryResult.iter({key: STR});
72    for (; it.valid(); it.next()) {
73      const arg = argColumn(attrs.tableName, attrs.argSetId, it.key);
74      if (attrs.alreadySelectedColumns.has(arg.alias)) continue;
75      this.argList.push(it.key);
76    }
77    raf.scheduleFullRedraw();
78  }
79
80  view({attrs}: m.Vnode<ArgumentSelectorAttrs>) {
81    if (this.argList === undefined) return m(Spinner);
82    return m(FilterableSelect, {
83      values: this.argList,
84      onSelected: (value: string) => attrs.onArgumentSelected(value),
85      maxDisplayedItems: MAX_ARGS_TO_DISPLAY,
86      autofocusInput: true,
87    });
88  }
89}
90