• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2022 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 {SortDirection} from '../base/comparison_utils';
16import {EqualsBuilder} from '../common/comparator_builder';
17import {ColumnType} from '../trace_processor/query_result';
18
19// Node in the hierarchical pivot tree. Only leaf nodes contain data from the
20// query result.
21export interface PivotTree {
22  // Whether the node should be collapsed in the UI, false by default and can
23  // be toggled with the button.
24  isCollapsed: boolean;
25
26  // Non-empty only in internal nodes.
27  children: Map<ColumnType, PivotTree>;
28  aggregates: ColumnType[];
29
30  // Non-empty only in leaf nodes.
31  rows: ColumnType[][];
32}
33
34export type AggregationFunction = 'COUNT' | 'SUM' | 'MIN' | 'MAX' | 'AVG';
35
36// Queried "table column" is either:
37// 1. A real one, represented as object with table and column name.
38// 2. Pseudo-column 'count' that's rendered as '1' in SQL to use in queries like
39// `select sum(1), name from slice group by name`.
40
41export interface RegularColumn {
42  kind: 'regular';
43  table: string;
44  column: string;
45}
46
47export interface ArgumentColumn {
48  kind: 'argument';
49  argument: string;
50}
51
52export type TableColumn = RegularColumn | ArgumentColumn;
53
54export function tableColumnEquals(t1: TableColumn, t2: TableColumn): boolean {
55  switch (t1.kind) {
56    case 'argument': {
57      return t2.kind === 'argument' && t1.argument === t2.argument;
58    }
59    case 'regular': {
60      return (
61        t2.kind === 'regular' &&
62        t1.table === t2.table &&
63        t1.column === t2.column
64      );
65    }
66  }
67}
68
69export function toggleEnabled<T>(
70  compare: (fst: T, snd: T) => boolean,
71  arr: T[],
72  column: T,
73  enabled: boolean,
74): void {
75  if (enabled && arr.find((value) => compare(column, value)) === undefined) {
76    arr.push(column);
77  }
78  if (!enabled) {
79    const index = arr.findIndex((value) => compare(column, value));
80    if (index !== -1) {
81      arr.splice(index, 1);
82    }
83  }
84}
85
86export interface Aggregation {
87  aggregationFunction: AggregationFunction;
88  column: TableColumn;
89
90  // If the aggregation is sorted, the field contains a sorting direction.
91  sortDirection?: SortDirection;
92}
93
94export function aggregationEquals(agg1: Aggregation, agg2: Aggregation) {
95  return new EqualsBuilder(agg1, agg2)
96    .comparePrimitive((agg) => agg.aggregationFunction)
97    .compare(tableColumnEquals, (agg) => agg.column)
98    .equals();
99}
100
101// Used to convert TableColumn to a string in order to store it in a Map, as
102// ES6 does not support compound Set/Map keys. This function should only be used
103// for interning keys, and does not have any requirements beyond different
104// TableColumn objects mapping to different strings.
105export function columnKey(tableColumn: TableColumn): string {
106  switch (tableColumn.kind) {
107    case 'argument': {
108      return `argument:${tableColumn.argument}`;
109    }
110    case 'regular': {
111      return `${tableColumn.table}.${tableColumn.column}`;
112    }
113  }
114}
115
116export function aggregationKey(aggregation: Aggregation): string {
117  return `${aggregation.aggregationFunction}:${columnKey(aggregation.column)}`;
118}
119