xref: /aosp_15_r20/external/perfetto/ui/src/components/tracks/custom_sql_table_slice_track.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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 {generateSqlWithInternalLayout} from '../sql_utils/layout';
16import {NAMED_ROW, NamedRow, NamedSliceTrack} from './named_slice_track';
17import {createView} from '../../trace_processor/sql_utils';
18import {Slice} from '../../public/track';
19import {AsyncDisposableStack} from '../../base/disposable_stack';
20import {sqlNameSafe} from '../../base/string_utils';
21import {Trace} from '../../public/trace';
22
23export interface CustomSqlImportConfig {
24  modules: string[];
25}
26
27export interface CustomSqlTableDefConfig {
28  // Table name
29  sqlTableName: string;
30  // Table columns
31  columns?: string[];
32  whereClause?: string;
33  disposable?: AsyncDisposable;
34}
35
36export abstract class CustomSqlTableSliceTrack extends NamedSliceTrack<
37  Slice,
38  NamedRow
39> {
40  protected readonly tableName;
41
42  constructor(trace: Trace, uri: string) {
43    super(trace, uri);
44    this.tableName = `customsqltableslicetrack_${sqlNameSafe(uri)}`;
45  }
46
47  getRowSpec(): NamedRow {
48    return NAMED_ROW;
49  }
50
51  rowToSlice(row: NamedRow): Slice {
52    return this.rowToSliceBase(row);
53  }
54
55  abstract getSqlDataSource():
56    | CustomSqlTableDefConfig
57    | Promise<CustomSqlTableDefConfig>;
58
59  getSqlImports(): CustomSqlImportConfig {
60    return {
61      modules: [] as string[],
62    };
63  }
64
65  async onInit() {
66    await this.loadImports();
67    const config = await Promise.resolve(this.getSqlDataSource());
68    let columns = ['*'];
69    if (config.columns !== undefined) {
70      columns = config.columns;
71    }
72    const trash = new AsyncDisposableStack();
73    config.disposable && trash.use(config.disposable);
74    trash.use(
75      await createView(
76        this.engine,
77        this.tableName,
78        generateSqlWithInternalLayout({
79          columns: columns,
80          sourceTable: config.sqlTableName,
81          ts: 'ts',
82          dur: 'dur',
83          whereClause: config.whereClause,
84        }),
85      ),
86    );
87    return trash;
88  }
89
90  getSqlSource(): string {
91    return `SELECT * FROM ${this.tableName}`;
92  }
93
94  async loadImports() {
95    for (const importModule of this.getSqlImports().modules) {
96      await this.engine.query(`INCLUDE PERFETTO MODULE ${importModule};`);
97    }
98  }
99}
100