blob: ac463e5b10a3eac6d469a8393a0e1f383ccac678 [file] [log] [blame]
// Copyright (C) 2021 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 {getHiddenPivotAlias} from './pivot_table_query_generator';
import {Row} from './query_result';
export const AVAILABLE_TABLES = ['slice'];
export const AVAILABLE_AGGREGATIONS = ['COUNT', 'SUM', 'AVG', 'MIN', 'MAX'];
export const WHERE_FILTERS = ['slice.dur != -1'];
export const SLICE_STACK_HELPER_COLUMNS =
['depth', 'stack_id', 'parent_stack_id'];
export const SLICE_STACK_COLUMN = 'name (stack)';
export const DEFAULT_PIVOT_TABLE_ID = 'pivot-table';
export const SLICE_AGGREGATION_PIVOT_TABLE_ID = 'pivot-table-slices';
export interface AggregationAttrs {
tableName: string;
columnName: string;
aggregation: string;
order: string;
}
export interface PivotAttrs {
tableName: string;
columnName: string;
isStackPivot: boolean;
}
export interface TableAttrs {
tableName: string;
columns: string[];
}
export interface ColumnAttrs {
name: string;
index: number;
tableName: string;
columnName: string;
aggregation?: string;
order?: string;
isStackColumn: boolean;
}
export interface RowAttrs {
row: Row;
expandableColumns: Set<string>; // Columns at which the row can be expanded.
expandedRows: Map<string, {
isExpanded: boolean,
rows: RowAttrs[]
}>; // Contains the expanded rows of each expanded expandableColumn.
whereFilters: Map<string, string>; // Where filters of each column that
// joins the row with its parent.
loadingColumn?: string;
depth: number;
}
export interface SubQueryAttrs {
rowIndices: number[];
columnIdx: number;
value: string;
expandedRowColumns: string[];
}
export interface SubQueryAttrs {
rowIndices: number[];
columnIdx: number;
value: string;
}
export interface PivotTableQueryResponse {
columns: ColumnAttrs[];
error?: string;
durationMs: number;
rows: RowAttrs[];
totalAggregations?: Row;
}
// Determine if the column provided is a stack column that can be expanded
// into descendants.
export function isStackPivot(tableName: string, columnName: string) {
if (tableName === 'slice' && columnName === SLICE_STACK_COLUMN) {
return true;
}
return false;
}
// Get the helper columns that are needed to expand a stack pivot.
export function getHiddenStackHelperColumns(pivot: PivotAttrs) {
const hiddenColumns: Array<{pivotAttrs: PivotAttrs, columnAlias: string}> =
[];
if (pivot.tableName === 'slice') {
for (const column of SLICE_STACK_HELPER_COLUMNS) {
const pivotAttrs = {
tableName: pivot.tableName,
columnName: column,
isStackPivot: false
};
hiddenColumns.push(
{pivotAttrs, columnAlias: getHiddenPivotAlias(pivotAttrs)});
}
}
return hiddenColumns;
}
// Removing unnecessary columns from table and adding stack column if it exists.
export function removeHiddenAndAddStackColumns(
tableName: string, columns: string[]) {
if (tableName === 'slice') {
// Removing "cat" and "slice_id" to maintain the original schema of the
// slice table that's compatible with descendant_slice_by_stack table.
columns = columns.filter(
column => ['stack_id', 'parent_stack_id', 'cat', 'slice_id'].includes(
column) === false);
columns.push(SLICE_STACK_COLUMN);
}
return columns;
}
// Get a list of tables that include the descendants that need to be queried.
export function getDescendantsTables(pivots: PivotAttrs[], stackId: string) {
const descendantsTables = [...AVAILABLE_TABLES];
let descendantsTable = 'undefined_table';
let replaceIdx = -1;
if (pivots.length > 0 && pivots[0].tableName === 'slice') {
// Replace slice table with descendants table.
descendantsTable = `descendant_slice_by_stack(${stackId}) AS slice`;
replaceIdx = descendantsTables.indexOf('slice');
if (replaceIdx === -1) {
throw Error('Slice table not found.');
}
}
if (pivots.length === 0 ||
!isStackPivot(pivots[0].tableName, pivots[0].columnName) ||
replaceIdx === -1) {
throw Error('Invalid Arguments to "getDescendantsTables"');
}
descendantsTables[replaceIdx] = descendantsTable;
return descendantsTables;
}
// Get the stack id column in the stack pivot table.
export function getStackColumn(pivot: PivotAttrs) {
if (pivot.tableName === 'slice') {
return {tableName: 'slice', columnName: 'stack_id', isStackPivot: false};
}
throw Error('"getStackColumn" called on pivot that is not a stack column.');
}
// Get the parent stack id column in the stack pivot table.
export function getParentStackColumn(pivot: PivotAttrs) {
if (pivot.tableName === 'slice') {
return {
tableName: 'slice',
columnName: 'parent_stack_id',
isStackPivot: false
};
}
throw Error(
'"getParentStackColumn" called on pivot that is not a stack column.');
}
// Get the depth column in the stack pivot table.
export function getStackDepthColumn(pivot: PivotAttrs) {
if (pivot.tableName === 'slice') {
return {tableName: 'slice', columnName: 'depth', isStackPivot: false};
}
throw Error(
'"getStackDepthColumn" called on pivot that is not a stack column.');
}
// Get a where filter that restricts the query by the given stack id.
export function getParentStackWhereFilter(pivot: PivotAttrs, stackId: string) {
const stackColumn = getStackColumn(pivot);
return `${stackColumn.tableName}.${stackColumn.columnName} = ${stackId}`;
}