• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2021 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 {getHiddenPivotAlias} from './pivot_table_query_generator';
16import {Row} from './query_result';
17
18export const AVAILABLE_TABLES = ['slice'];
19export const AVAILABLE_AGGREGATIONS = ['COUNT', 'SUM', 'AVG', 'MIN', 'MAX'];
20export const WHERE_FILTERS = ['slice.dur != -1'];
21export const SLICE_STACK_HELPER_COLUMNS =
22    ['depth', 'stack_id', 'parent_stack_id'];
23export const SLICE_STACK_COLUMN = 'name (stack)';
24export const DEFAULT_PIVOT_TABLE_ID = 'pivot-table';
25export const SLICE_AGGREGATION_PIVOT_TABLE_ID = 'pivot-table-slices';
26
27export interface AggregationAttrs {
28  tableName: string;
29  columnName: string;
30  aggregation: string;
31  order: string;
32}
33
34export interface PivotAttrs {
35  tableName: string;
36  columnName: string;
37  isStackPivot: boolean;
38}
39
40export interface TableAttrs {
41  tableName: string;
42  columns: string[];
43}
44
45export interface ColumnAttrs {
46  name: string;
47  index: number;
48  tableName: string;
49  columnName: string;
50  aggregation?: string;
51  order?: string;
52  isStackColumn: boolean;
53}
54
55export interface RowAttrs {
56  row: Row;
57  expandableColumns: Set<string>;  // Columns at which the row can be expanded.
58  expandedRows: Map<string, {
59    isExpanded: boolean,
60    rows: RowAttrs[]
61  }>;  // Contains the expanded rows of each expanded expandableColumn.
62  whereFilters: Map<string, string>;  // Where filters of each column that
63                                      // joins the row with its parent.
64  loadingColumn?: string;
65  depth: number;
66}
67
68export interface SubQueryAttrs {
69  rowIndices: number[];
70  columnIdx: number;
71  value: string;
72  expandedRowColumns: string[];
73}
74
75export interface SubQueryAttrs {
76  rowIndices: number[];
77  columnIdx: number;
78  value: string;
79}
80
81export interface PivotTableQueryResponse {
82  columns: ColumnAttrs[];
83  error?: string;
84  durationMs: number;
85  rows: RowAttrs[];
86  totalAggregations?: Row;
87}
88
89// Determine if the column provided is a stack column that can be expanded
90// into descendants.
91export function isStackPivot(tableName: string, columnName: string) {
92  if (tableName === 'slice' && columnName === SLICE_STACK_COLUMN) {
93    return true;
94  }
95  return false;
96}
97
98// Get the helper columns that are needed to expand a stack pivot.
99export function getHiddenStackHelperColumns(pivot: PivotAttrs) {
100  const hiddenColumns: Array<{pivotAttrs: PivotAttrs, columnAlias: string}> =
101      [];
102  if (pivot.tableName === 'slice') {
103    for (const column of SLICE_STACK_HELPER_COLUMNS) {
104      const pivotAttrs = {
105        tableName: pivot.tableName,
106        columnName: column,
107        isStackPivot: false
108      };
109      hiddenColumns.push(
110          {pivotAttrs, columnAlias: getHiddenPivotAlias(pivotAttrs)});
111    }
112  }
113  return hiddenColumns;
114}
115
116// Removing unnecessary columns from table and adding stack column if it exists.
117export function removeHiddenAndAddStackColumns(
118    tableName: string, columns: string[]) {
119  if (tableName === 'slice') {
120    // Removing "cat" and "slice_id" to maintain the original schema of the
121    // slice table that's compatible with descendant_slice_by_stack table.
122    columns = columns.filter(
123        column => ['stack_id', 'parent_stack_id', 'cat', 'slice_id'].includes(
124                      column) === false);
125    columns.push(SLICE_STACK_COLUMN);
126  }
127  return columns;
128}
129
130// Get a list of tables that include the descendants that need to be queried.
131export function getDescendantsTables(pivots: PivotAttrs[], stackId: string) {
132  const descendantsTables = [...AVAILABLE_TABLES];
133  let descendantsTable = 'undefined_table';
134  let replaceIdx = -1;
135  if (pivots.length > 0 && pivots[0].tableName === 'slice') {
136    // Replace slice table with descendants table.
137    descendantsTable = `descendant_slice_by_stack(${stackId}) AS slice`;
138    replaceIdx = descendantsTables.indexOf('slice');
139    if (replaceIdx === -1) {
140      throw Error('Slice table not found.');
141    }
142  }
143  if (pivots.length === 0 ||
144      !isStackPivot(pivots[0].tableName, pivots[0].columnName) ||
145      replaceIdx === -1) {
146    throw Error('Invalid Arguments to "getDescendantsTables"');
147  }
148  descendantsTables[replaceIdx] = descendantsTable;
149  return descendantsTables;
150}
151
152// Get the stack id column in the stack pivot table.
153export function getStackColumn(pivot: PivotAttrs) {
154  if (pivot.tableName === 'slice') {
155    return {tableName: 'slice', columnName: 'stack_id', isStackPivot: false};
156  }
157  throw Error('"getStackColumn" called on pivot that is not a stack column.');
158}
159
160// Get the parent stack id column in the stack pivot table.
161export function getParentStackColumn(pivot: PivotAttrs) {
162  if (pivot.tableName === 'slice') {
163    return {
164      tableName: 'slice',
165      columnName: 'parent_stack_id',
166      isStackPivot: false
167    };
168  }
169  throw Error(
170      '"getParentStackColumn" called on pivot that is not a stack column.');
171}
172
173// Get the depth column in the stack pivot table.
174export function getStackDepthColumn(pivot: PivotAttrs) {
175  if (pivot.tableName === 'slice') {
176    return {tableName: 'slice', columnName: 'depth', isStackPivot: false};
177  }
178  throw Error(
179      '"getStackDepthColumn" called on pivot that is not a stack column.');
180}
181
182// Get a where filter that restricts the query by the given stack id.
183export function getParentStackWhereFilter(pivot: PivotAttrs, stackId: string) {
184  const stackColumn = getStackColumn(pivot);
185  return `${stackColumn.tableName}.${stackColumn.columnName} = ${stackId}`;
186}
187