ui: make UI use the iterator API of trace processor

As the iterator API is the new (and soon only) API for all clients of trace
processor, switch over the UI to use the iterator API. We recreate
the RawQuery proto to allow us to not change all usages of the proto
in the UI.

Bug: 118867986
Change-Id: I0beb868eaecf3cc7113035583fd3e7ad345420d9
diff --git a/src/trace_processor/wasm_bridge.cc b/src/trace_processor/wasm_bridge.cc
index 1fe783f..e05a79b 100644
--- a/src/trace_processor/wasm_bridge.cc
+++ b/src/trace_processor/wasm_bridge.cc
@@ -98,15 +98,94 @@
     return;
   }
 
-  // When the C++ class implementing the service replies, serialize the protobuf
-  // result and post it back to the worker script (|g_reply|).
-  auto callback = [id](const protos::RawQueryResult& res) {
-    std::string encoded;
-    res.SerializeToString(&encoded);
-    g_reply(id, true, encoded.data(), static_cast<uint32_t>(encoded.size()));
-  };
+  using ColumnDesc = protos::RawQueryResult::ColumnDesc;
+  protos::RawQueryResult result;
+  auto it = g_trace_processor->ExecuteQuery(query.sql_query().c_str());
+  for (uint32_t col = 0; col < it.ColumnCount(); ++col) {
+    // Setup the descriptors.
+    auto* descriptor = result.add_column_descriptors();
+    descriptor->set_name(it.GetColumName(col));
+    descriptor->set_type(ColumnDesc::UNKNOWN);
 
-  g_trace_processor->ExecuteQuery(query, callback);
+    // Add an empty column.
+    result.add_columns();
+  }
+
+  for (uint32_t rows = 0; it.Next(); ++rows) {
+    for (uint32_t col = 0; col < it.ColumnCount(); ++col) {
+      auto* column = result.mutable_columns(static_cast<int>(col));
+      auto* desc = result.mutable_column_descriptors(static_cast<int>(col));
+
+      using SqlValue = trace_processor::SqlValue;
+      auto cell = it.Get(col);
+      if (desc->type() == ColumnDesc::UNKNOWN) {
+        switch (cell.type) {
+          case SqlValue::Type::kLong:
+            desc->set_type(ColumnDesc::LONG);
+            break;
+          case SqlValue::Type::kString:
+            desc->set_type(ColumnDesc::STRING);
+            break;
+          case SqlValue::Type::kDouble:
+            desc->set_type(ColumnDesc::DOUBLE);
+            break;
+          case SqlValue::Type::kNull:
+            break;
+        }
+      }
+
+      // If either the column type is null or we still don't know the type,
+      // just add null values to all the columns.
+      if (cell.type == SqlValue::Type::kNull ||
+          desc->type() == ColumnDesc::UNKNOWN) {
+        column->add_long_values(0);
+        column->add_string_values("[NULL]");
+        column->add_double_values(0);
+        column->add_is_nulls(true);
+        continue;
+      }
+
+      // Cast the sqlite value to the type of the column.
+      switch (desc->type()) {
+        case ColumnDesc::LONG:
+          PERFETTO_CHECK(cell.type == SqlValue::Type::kLong ||
+                         cell.type == SqlValue::Type::kDouble);
+          if (cell.type == SqlValue::Type::kLong) {
+            column->add_long_values(cell.long_value);
+          } else /* if (cell.type == SqlValue::Type::kDouble) */ {
+            column->add_long_values(static_cast<int64_t>(cell.double_value));
+          }
+          column->add_is_nulls(false);
+          break;
+        case ColumnDesc::STRING: {
+          PERFETTO_CHECK(cell.type == SqlValue::Type::kString);
+          column->add_string_values(cell.string_value);
+          column->add_is_nulls(false);
+          break;
+        }
+        case ColumnDesc::DOUBLE:
+          PERFETTO_CHECK(cell.type == SqlValue::Type::kLong ||
+                         cell.type == SqlValue::Type::kDouble);
+          if (cell.type == SqlValue::Type::kLong) {
+            column->add_double_values(static_cast<double>(cell.long_value));
+          } else /* if (cell.type == SqlValue::Type::kDouble) */ {
+            column->add_double_values(cell.double_value);
+          }
+          column->add_is_nulls(false);
+          break;
+        case ColumnDesc::UNKNOWN:
+          PERFETTO_FATAL("Handled in if statement above.");
+      }
+    }
+    result.set_num_records(rows + 1);
+  }
+  if (auto opt_error = it.GetLastError()) {
+    result.set_error(*opt_error);
+  }
+
+  std::string encoded;
+  result.SerializeToString(&encoded);
+  g_reply(id, true, encoded.data(), static_cast<uint32_t>(encoded.size()));
 }
 
 }  // extern "C"