tp: Implement IntervalTreeAgg (without partitioning)

Change-Id: Ic01c44219abfa36fbe49ff00a3b84a1df6eec13c
diff --git a/BUILD b/BUILD
index 8b75b3d..e12e6d1 100644
--- a/BUILD
+++ b/BUILD
@@ -2471,6 +2471,7 @@
     name = "src_trace_processor_perfetto_sql_intrinsics_types_types",
     srcs = [
         "src/trace_processor/perfetto_sql/intrinsics/types/array.h",
+        "src/trace_processor/perfetto_sql/intrinsics/types/interval_tree.h",
         "src/trace_processor/perfetto_sql/intrinsics/types/node.h",
         "src/trace_processor/perfetto_sql/intrinsics/types/row_dataframe.h",
         "src/trace_processor/perfetto_sql/intrinsics/types/struct.h",
diff --git a/src/trace_processor/perfetto_sql/intrinsics/functions/type_builders.cc b/src/trace_processor/perfetto_sql/intrinsics/functions/type_builders.cc
index bd99fa3..079d23b 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/functions/type_builders.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/functions/type_builders.cc
@@ -32,6 +32,7 @@
 #include "perfetto/public/compiler.h"
 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/types/array.h"
+#include "src/trace_processor/perfetto_sql/intrinsics/types/interval_tree.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/types/node.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/types/row_dataframe.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/types/struct.h"
@@ -270,6 +271,45 @@
   }
 };
 
+struct IntervalTreeIntervalsAgg
+    : public SqliteAggregateFunction<perfetto_sql::SortedIntervals> {
+  static constexpr char kName[] = "__intrinsic_interval_tree_intervals_agg";
+  static constexpr int kArgCount = 3;
+  struct AggCtx : SqliteAggregateContext<AggCtx> {
+    std::vector<IntervalTree::Interval> intervals;
+  };
+
+  static void Step(sqlite3_context* ctx, int rargc, sqlite3_value** argv) {
+    auto argc = static_cast<uint32_t>(rargc);
+    if (argc != kArgCount) {
+      return sqlite::result::Error(
+          ctx, "INTERVAL_TREE_AGG: must have exactly 3 arguments");
+    }
+
+    auto& agg_ctx = AggCtx::GetOrCreateContextForStep(ctx);
+    for (uint32_t i = 0; i < argc; i++) {
+      IntervalTree::Interval interval;
+      interval.id = static_cast<uint32_t>(sqlite::value::Int64(argv[0]));
+      interval.start = static_cast<uint64_t>(sqlite::value::Int64(argv[1]));
+      interval.end =
+          interval.start + static_cast<uint64_t>(sqlite::value::Int64(argv[2]));
+      agg_ctx.intervals.push_back(std::move(interval));
+    }
+  }
+
+  static void Final(sqlite3_context* ctx) {
+    auto raw_agg_ctx = AggCtx::GetContextOrNullForFinal(ctx);
+    if (!raw_agg_ctx) {
+      return sqlite::result::Null(ctx);
+    }
+    return sqlite::result::UniquePointer(
+        ctx,
+        std::make_unique<perfetto_sql::SortedIntervals>(
+            std::move(raw_agg_ctx.get()->intervals)),
+        "INTERVAL_TREE_INTERVALS");
+  }
+};
+
 }  // namespace
 
 base::Status RegisterTypeBuilderFunctions(PerfettoSqlEngine& engine) {
@@ -277,6 +317,9 @@
   RETURN_IF_ERROR(engine.RegisterSqliteFunction<Struct>(nullptr));
   RETURN_IF_ERROR(
       engine.RegisterSqliteAggregateFunction<RowDataframeAgg>(nullptr));
+  RETURN_IF_ERROR(
+      engine.RegisterSqliteAggregateFunction<IntervalTreeIntervalsAgg>(
+          nullptr));
   return engine.RegisterSqliteAggregateFunction<NodeAgg>(nullptr);
 }
 
diff --git a/src/trace_processor/perfetto_sql/intrinsics/types/BUILD.gn b/src/trace_processor/perfetto_sql/intrinsics/types/BUILD.gn
index 0993dfe..2f17251 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/types/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/intrinsics/types/BUILD.gn
@@ -20,10 +20,14 @@
 source_set("types") {
   sources = [
     "array.h",
+    "interval_tree.h",
     "node.h",
     "row_dataframe.h",
     "struct.h",
     "value.h",
   ]
-  deps = [ "../../../../../gn:default_deps" ]
+  deps = [
+    "../../../../../gn:default_deps",
+    "../../../containers",
+  ]
 }
diff --git a/src/trace_processor/perfetto_sql/intrinsics/types/interval_tree.h b/src/trace_processor/perfetto_sql/intrinsics/types/interval_tree.h
new file mode 100644
index 0000000..d92ef72
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/intrinsics/types/interval_tree.h
@@ -0,0 +1,31 @@
+/*
+ * 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 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_TYPES_INTERVAL_TREE_H_
+#define SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_TYPES_INTERVAL_TREE_H_
+
+#include <cstdint>
+#include <string>
+#include <vector>
+#include "src/trace_processor/containers/interval_tree.h"
+
+namespace perfetto::trace_processor::perfetto_sql {
+
+using SortedIntervals = std::vector<IntervalTree::Interval>;
+
+}  // namespace perfetto::trace_processor::perfetto_sql
+
+#endif  // SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_TYPES_INTERVAL_TREE_H_