• 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 {Anchor} from '../../widgets/anchor';
17import {Icons} from '../../base/semantic_icons';
18import {Trace} from '../../public/trace';
19import {QueryResult, Row} from '../../trace_processor/query_result';
20import {SqlRef} from '../../widgets/sql_ref';
21import {SqlTableDescription} from '../../components/widgets/sql/table/table_description';
22import {MenuItem} from '../../widgets/menu';
23import {extensions} from '../../components/extensions';
24
25export const SCROLLS_TRACK_URI = 'perfetto.ChromeScrollJank#toplevelScrolls';
26export const EVENT_LATENCY_TRACK_URI = 'perfetto.ChromeScrollJank#eventLatency';
27export const JANKS_TRACK_URI = 'perfetto.ChromeScrollJank#scrollJankV3';
28
29export function renderSliceRef(args: {
30  trace: Trace;
31  id: number;
32  trackUri: string;
33  title: m.Children;
34}) {
35  return m(
36    Anchor,
37    {
38      icon: Icons.UpdateSelection,
39      onclick: () => {
40        args.trace.selection.selectTrackEvent(args.trackUri, args.id, {
41          scrollToSelection: true,
42        });
43      },
44    },
45    args.title,
46  );
47}
48
49export function renderSqlRef(args: {
50  trace: Trace;
51  tableName: string;
52  tableDescription: SqlTableDescription | undefined;
53  id: number | bigint;
54}) {
55  return m(SqlRef, {
56    table: args.tableName,
57    id: args.id,
58    additionalMenuItems: args.tableDescription && [
59      m(MenuItem, {
60        label: 'Show query results',
61        icon: 'table',
62        onclick: () =>
63          extensions.addLegacySqlTableTab(args.trace, {
64            table: args.tableDescription!,
65            filters: [
66              {
67                op: ([columnName]) => `${columnName} = ${args.id}`,
68                columns: ['id'],
69              },
70            ],
71          }),
72      }),
73    ],
74  });
75}
76
77/**
78 * Returns an array of the rows in `queryResult`.
79 *
80 * Warning: Only use this function in contexts where the number of rows is
81 * guaranteed to be small. Prefer doing transformations in SQL where possible.
82 */
83export function rows<R extends Row>(queryResult: QueryResult, spec: R): R[] {
84  const results: R[] = [];
85  for (const it = queryResult.iter(spec); it.valid(); it.next()) {
86    const row: Row = {};
87    for (const key of Object.keys(spec)) {
88      row[key] = it[key];
89    }
90    results.push(row as R);
91  }
92  return results;
93}
94
95/**
96 * Converts a number to a boolean according to SQLite's conversion rules.
97 *
98 * See https://www.sqlite.org/lang_expr.html#boolean_expressions.
99 */
100export function fromSqlBool(value: number): boolean;
101export function fromSqlBool(value: null): undefined;
102export function fromSqlBool(value: number | null): boolean | undefined;
103export function fromSqlBool(value: number | null): boolean | undefined {
104  if (value === null) {
105    return undefined;
106  } else {
107    return value !== 0;
108  }
109}
110