Merge "ui: add support for contextual columns in QueryFlamegraph" into main
diff --git a/Android.bp b/Android.bp
index 19fd289..2bcbd0e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13338,6 +13338,7 @@
         "src/trace_processor/perfetto_sql/stdlib/linux/memory/process.sql",
         "src/trace_processor/perfetto_sql/stdlib/linux/perf/samples.sql",
         "src/trace_processor/perfetto_sql/stdlib/metasql/column_list.sql",
+        "src/trace_processor/perfetto_sql/stdlib/metasql/table_list.sql",
         "src/trace_processor/perfetto_sql/stdlib/pkvm/hypervisor.sql",
         "src/trace_processor/perfetto_sql/stdlib/prelude/casts.sql",
         "src/trace_processor/perfetto_sql/stdlib/prelude/slices.sql",
diff --git a/BUILD b/BUILD
index bcc3650..8339af3 100644
--- a/BUILD
+++ b/BUILD
@@ -2776,6 +2776,7 @@
     name = "src_trace_processor_perfetto_sql_stdlib_metasql_metasql",
     srcs = [
         "src/trace_processor/perfetto_sql/stdlib/metasql/column_list.sql",
+        "src/trace_processor/perfetto_sql/stdlib/metasql/table_list.sql",
     ],
 )
 
diff --git a/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc b/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc
index b5bcc47..915082a 100644
--- a/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc
+++ b/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc
@@ -144,13 +144,14 @@
       SqlSource::FromTraceProcessorImplementation("SELECT 0 WHERE 0"));
 }
 
-constexpr std::array<const char*, 6> kTokensAllowedInMacro({
+constexpr std::array<const char*, 7> kTokensAllowedInMacro({
+    "_ColumnNameList",
+    "_Macro",
+    "_SqlFragment",
+    "_TableNameList",
     "ColumnName",
     "Expr",
     "TableOrSubquery",
-    "_ColumnNameList",
-    "_SqlFragment",
-    "_Macro",
 });
 
 bool IsTokenAllowedInMacro(const std::string& view) {
diff --git a/src/trace_processor/perfetto_sql/stdlib/metasql/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/metasql/BUILD.gn
index a67a2a1..a82b2d2 100644
--- a/src/trace_processor/perfetto_sql/stdlib/metasql/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/metasql/BUILD.gn
@@ -15,5 +15,8 @@
 import("../../../../../gn/perfetto_sql.gni")
 
 perfetto_sql_source_set("metasql") {
-  sources = [ "column_list.sql" ]
+  sources = [
+    "column_list.sql",
+    "table_list.sql",
+  ]
 }
diff --git a/src/trace_processor/perfetto_sql/stdlib/metasql/table_list.sql b/src/trace_processor/perfetto_sql/stdlib/metasql/table_list.sql
new file mode 100644
index 0000000..6070d8b
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/metasql/table_list.sql
@@ -0,0 +1,23 @@
+--
+-- Copyright 2024 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
+--
+--     https://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.
+
+-- Given a list of table names, applies an arbitrary macro to each table
+-- and joins the result with a comma.
+CREATE PERFETTO MACRO _metasql_map_join_table_list(
+  tables _TableNameList,
+  map_macro _Macro
+)
+RETURNS _SqlFragment
+AS __intrinsic_token_map_join!($tables, $map_macro, __intrinsic_token_comma!());
diff --git a/test/trace_processor/diff_tests/include_index.py b/test/trace_processor/diff_tests/include_index.py
index 9a5b419..1012f80 100644
--- a/test/trace_processor/diff_tests/include_index.py
+++ b/test/trace_processor/diff_tests/include_index.py
@@ -122,6 +122,7 @@
 from diff_tests.stdlib.linux.cpu import LinuxCpu
 from diff_tests.stdlib.linux.memory import Memory
 from diff_tests.stdlib.metasql.column_list import ColumnListTests
+from diff_tests.stdlib.metasql.table_list import TableListTests
 from diff_tests.stdlib.pkvm.tests import Pkvm
 from diff_tests.stdlib.prelude.math_functions_tests import PreludeMathFunctions
 from diff_tests.stdlib.prelude.pprof_functions_tests import PreludePprofFunctions
@@ -294,6 +295,8 @@
                      'DynamicTables').fetch(),
       *ColumnListTests(index_path, 'stdlib/column_list',
                        'ColumnListTests').fetch(),
+      *TableListTests(index_path, 'stdlib/table_list',
+                      'TableListTests').fetch(),
       *Memory(index_path, 'stdlib/linux', 'Memory').fetch(),
       *PreludeMathFunctions(index_path, 'stdlib/prelude',
                             'PreludeMathFunctions').fetch(),
diff --git a/test/trace_processor/diff_tests/stdlib/metasql/table_list.py b/test/trace_processor/diff_tests/stdlib/metasql/table_list.py
new file mode 100644
index 0000000..d1a69c6
--- /dev/null
+++ b/test/trace_processor/diff_tests/stdlib/metasql/table_list.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+# Copyright (C) 2024 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 a
+#
+#      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.
+
+from python.generators.diff_tests.testing import Csv, TextProto
+from python.generators.diff_tests.testing import DiffTestBlueprint
+from python.generators.diff_tests.testing import TestSuite
+
+
+class TableListTests(TestSuite):
+
+  def test_table_list_result_columns(self):
+    return DiffTestBlueprint(
+        trace=TextProto(''),
+        query="""
+        INCLUDE PERFETTO MODULE metasql.table_list;
+
+        CREATE PERFETTO MACRO mac(t TableOrSubquery)
+        RETURNS TableOrSubquery AS
+        (SELECT * FROM $t);
+
+        WITH foo AS (
+          SELECT 0 AS a
+        ),
+        bar AS (
+          SELECT 1 AS b
+        ),
+        baz AS (
+          SELECT 2 AS c
+        )
+        SELECT a + b + c
+        FROM _metasql_map_join_table_list!((foo, bar, baz), mac);
+        """,
+        out=Csv("""
+        "a + b + c"
+        3
+        """))
diff --git a/ui/.eslintrc.js b/ui/.eslintrc.js
index db775ea..29392be 100644
--- a/ui/.eslintrc.js
+++ b/ui/.eslintrc.js
@@ -28,14 +28,14 @@
     }],
 
     // Formatting handled by prettier
-    "indent": "off",
-    'max-len': "off",
-    "operator-linebreak": "off",
-    "quotes": "off",
-    "brace-style": "off",
-    "space-before-function-paren": "off",
-    "generator-star-spacing": "off",
-    "semi-spacing": "off",
+    'indent': 'off',
+    'max-len': 'off',
+    'operator-linebreak': 'off',
+    'quotes': 'off',
+    'brace-style': 'off',
+    'space-before-function-paren': 'off',
+    'generator-star-spacing': 'off',
+    'semi-spacing': 'off',
 
     // clang-format --js used to format EOL comments after (e.g.) an if like:
     // if (foo) {  // insightful comment
diff --git a/ui/src/assets/track_panel.scss b/ui/src/assets/track_panel.scss
index 6deb6b7..64615b8 100644
--- a/ui/src/assets/track_panel.scss
+++ b/ui/src/assets/track_panel.scss
@@ -242,7 +242,7 @@
 }
 
 .pf-track-details-dropdown {
-  width: 400px;
+  max-width: 400px;
 }
 
 .pf-panel-group {
diff --git a/ui/src/assets/widgets/popup.scss b/ui/src/assets/widgets/popup.scss
index e2884a7..6d26981 100644
--- a/ui/src/assets/widgets/popup.scss
+++ b/ui/src/assets/widgets/popup.scss
@@ -17,6 +17,10 @@
 .pf-popup-portal {
   position: absolute;
   z-index: 10; // Hack to show popups over certain other elements
+
+  // When width = 0 it can cause layout issues in popup content, so we give this
+  // element some width manually
+  width: 100%;
 }
 
 .pf-popup {
diff --git a/ui/src/assets/widgets/tree.scss b/ui/src/assets/widgets/tree.scss
index 0f6604b..ffcbf91 100644
--- a/ui/src/assets/widgets/tree.scss
+++ b/ui/src/assets/widgets/tree.scss
@@ -28,8 +28,9 @@
       background: inherit;
       padding: 0 0 0 15px;
       border-radius: 0 $pf-border-radius $pf-border-radius 0;
-      word-break: break-all;
+      overflow-wrap: break-word; // Break words if overflowing
       white-space: pre-wrap;
+      min-width: 0; // Allow column to shrink past content if container is thin
     }
 
     .pf-tree-gutter {