• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2025 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 protos from '../../protos';
16import m from 'mithril';
17import {
18  ColumnControllerRow,
19  columnControllerRowFromName,
20  newColumnControllerRows,
21} from './query_builder/column_controller';
22import {
23  GroupByAgg,
24  placeholderNewColumnName,
25} from './query_builder/operations/groupy_by';
26import {Filter} from './query_builder/operations/filter';
27
28export enum NodeType {
29  // Sources
30  kStdlibTable,
31  kSimpleSlices,
32  kSqlSource,
33}
34
35// All information required to create a new node.
36export interface QueryNodeState {
37  prevNode?: QueryNode;
38  sourceCols: ColumnControllerRow[];
39
40  filters: Filter[];
41  groupByColumns: ColumnControllerRow[];
42  aggregations: GroupByAgg[];
43}
44
45export interface QueryNode {
46  readonly type: NodeType;
47  readonly prevNode?: QueryNode;
48  readonly nextNode?: QueryNode;
49
50  // Columns that are available in the source data.
51  readonly sourceCols: ColumnControllerRow[];
52
53  // Columns that are available after applying all operations.
54  readonly finalCols: ColumnControllerRow[];
55
56  // State of the node. This is used to store the user's input and can be used
57  // to fully recover the node.
58  readonly state: QueryNodeState;
59
60  validate(): boolean;
61  getTitle(): string;
62  getDetails(): m.Child;
63  getState(): QueryNodeState;
64  getStructuredQuery(): protos.PerfettoSqlStructuredQuery | undefined;
65}
66
67export function createSelectColumnsProto(
68  node: QueryNode,
69): protos.PerfettoSqlStructuredQuery.SelectColumn[] | undefined {
70  if (node.finalCols.every((c) => c.checked)) return;
71  const selectedColumns: protos.PerfettoSqlStructuredQuery.SelectColumn[] = [];
72
73  for (const c of node.finalCols) {
74    if (c.checked === false) continue;
75    const newC = new protos.PerfettoSqlStructuredQuery.SelectColumn();
76    newC.columnName = c.column.name;
77    if (c.alias) {
78      newC.alias = c.alias;
79    }
80    selectedColumns.push(newC);
81  }
82  return selectedColumns;
83}
84
85export function createFinalColumns(node: QueryNode) {
86  if (node.state.groupByColumns.find((c) => c.checked)) {
87    const selected = node.state.groupByColumns.filter((c) => c.checked);
88    for (const agg of node.state.aggregations) {
89      selected.push(
90        columnControllerRowFromName(
91          agg.newColumnName ?? placeholderNewColumnName(agg),
92        ),
93      );
94    }
95    return newColumnControllerRows(selected, true);
96  }
97
98  return newColumnControllerRows(node.sourceCols, true);
99}
100