blob: f7cd374a9319bda4d107bde5e195945994cadd4f [file] [log] [blame]
// Copyright (C) 2023 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import m from 'mithril';
import {raf} from '../../core/raf_scheduler';
import {EngineProxy} from '../../trace_processor/engine';
import {STR} from '../../trace_processor/query_result';
import {FilterableSelect} from '../../widgets/select';
import {Spinner} from '../../widgets/spinner';
import {
constraintsToQueryPrefix,
constraintsToQuerySuffix,
SQLConstraints,
} from '../sql_utils';
import {argColumn} from './column';
import {ArgSetIdColumn} from './table_description';
const MAX_ARGS_TO_DISPLAY = 15;
interface ArgumentSelectorAttrs {
engine: EngineProxy;
argSetId: ArgSetIdColumn;
tableName: string;
constraints: SQLConstraints;
// List of aliases for existing columns by the table.
alreadySelectedColumns: Set<string>;
onArgumentSelected: (argument: string) => void;
}
// A widget which allows the user to select a new argument to display.
// Dinamically queries Trace Processor to find the relevant set of arg_set_ids
// and which args are present in these arg sets.
export class ArgumentSelector implements
m.ClassComponent<ArgumentSelectorAttrs> {
argList?: string[];
constructor({attrs}: m.Vnode<ArgumentSelectorAttrs>) {
this.load(attrs);
}
private async load(attrs: ArgumentSelectorAttrs) {
const queryResult = await attrs.engine.query(`
-- Encapsulate the query in a CTE to avoid clashes between filters
-- and columns of the 'args' table.
WITH arg_sets AS (
${constraintsToQueryPrefix(attrs.constraints)}
SELECT DISTINCT ${attrs.tableName}.${attrs.argSetId.name} as arg_set_id
FROM ${attrs.tableName}
${constraintsToQuerySuffix(attrs.constraints)}
)
SELECT
DISTINCT args.key as key
FROM arg_sets
JOIN args USING (arg_set_id)
`);
this.argList = [];
const it = queryResult.iter({key: STR});
for (; it.valid(); it.next()) {
const arg = argColumn(attrs.tableName, attrs.argSetId, it.key);
if (attrs.alreadySelectedColumns.has(arg.alias)) continue;
this.argList.push(it.key);
}
raf.scheduleFullRedraw();
}
view({attrs}: m.Vnode<ArgumentSelectorAttrs>) {
if (this.argList === undefined) return m(Spinner);
return m(FilterableSelect, {
values: this.argList,
onSelected: (value: string) => attrs.onArgumentSelected(value),
maxDisplayedItems: MAX_ARGS_TO_DISPLAY,
autofocusInput: true,
});
}
}