1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "src/trace_processor/db/view.h" 18 19 #ifndef SRC_TRACE_PROCESSOR_VIEWS_MACROS_INTERNAL_H_ 20 #define SRC_TRACE_PROCESSOR_VIEWS_MACROS_INTERNAL_H_ 21 22 namespace perfetto { 23 namespace trace_processor { 24 namespace macros_internal { 25 26 template <typename T> 27 class ViewColumnBlueprint { 28 public: 29 using sql_value_type = typename TypedColumn<T>::sql_value_type; 30 ViewColumnBlueprint(uint32_t index_in_view)31 explicit ViewColumnBlueprint(uint32_t index_in_view) 32 : index_in_view_(index_in_view) {} 33 34 // Returns an Order for each Order type for this ColumnBlueprint. eq(sql_value_type v)35 Constraint eq(sql_value_type v) const { 36 return Constraint{index_in_view_, FilterOp::kEq, ToValue(v)}; 37 } gt(sql_value_type v)38 Constraint gt(sql_value_type v) const { 39 return Constraint{index_in_view_, FilterOp::kGt, ToValue(v)}; 40 } lt(sql_value_type v)41 Constraint lt(sql_value_type v) const { 42 return Constraint{index_in_view_, FilterOp::kLt, ToValue(v)}; 43 } ne(sql_value_type v)44 Constraint ne(sql_value_type v) const { 45 return Constraint{index_in_view_, FilterOp::kNe, ToValue(v)}; 46 } ge(sql_value_type v)47 Constraint ge(sql_value_type v) const { 48 return Constraint{index_in_view_, FilterOp::kGe, ToValue(v)}; 49 } le(sql_value_type v)50 Constraint le(sql_value_type v) const { 51 return Constraint{index_in_view_, FilterOp::kLe, ToValue(v)}; 52 } 53 54 // Returns an Order for each Order type for this ColumnBlueprint. ascending()55 Order ascending() const { return Order{index_in_view_, false}; } descending()56 Order descending() const { return Order{index_in_view_, true}; } 57 58 private: ToValue(double value)59 static SqlValue ToValue(double value) { return SqlValue::Double(value); } ToValue(uint32_t value)60 static SqlValue ToValue(uint32_t value) { return SqlValue::Long(value); } ToValue(int64_t value)61 static SqlValue ToValue(int64_t value) { return SqlValue::Long(value); } ToValue(NullTermStringView value)62 static SqlValue ToValue(NullTermStringView value) { 63 return SqlValue::String(value.c_str()); 64 } 65 66 uint32_t index_in_view_ = 0; 67 }; 68 69 // Ignore GCC warning about a missing argument for a variadic macro parameter. 70 #if defined(__GNUC__) || defined(__clang__) 71 #pragma GCC system_header 72 #endif 73 74 // Basic helper macros. 75 #define PERFETTO_TP_NOOP(...) 76 77 // Invokes FN on each column in the definition of the table. We define a 78 // recursive macro as we need to walk up the hierarchy until we hit the root. 79 // Currently, we hardcode 5 levels but this can be increased as necessary. 80 #define PERFETTO_TP_ALL_COLUMNS(DEF, arg) \ 81 DEF(PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, arg) 82 83 // Invokes a View column function using data from a table column definition. 84 #define PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE(FN, col_name) \ 85 FN(col_name, from_table, col_name) 86 87 // Invokes FN on the name and class name declaration of the view. 88 #define PERFETTO_TP_VIEW_NAME(DEF, FN) \ 89 DEF(FN, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, \ 90 PERFETTO_TP_NOOP) 91 92 // Invokes FN on every table which is part of the view definition. 93 #define PERFETTO_TP_VIEW_FROM(DEF, FN) \ 94 DEF(PERFETTO_TP_NOOP, FN, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, \ 95 PERFETTO_TP_NOOP) 96 97 // Invokes FN on every join which is part of the view definition. 98 #define PERFETTO_TP_VIEW_JOINS(DEF, FN) \ 99 DEF(PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, FN, PERFETTO_TP_NOOP, \ 100 PERFETTO_TP_NOOP) 101 102 // Invokes FN on every column which is part of the view definition. 103 #define PERFETTO_TP_VIEW_COLUMNS(DEF, FROM_FROM_COLUMN_FN, FN) \ 104 DEF(PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, \ 105 FROM_FROM_COLUMN_FN) \ 106 DEF(PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, FN, \ 107 PERFETTO_TP_NOOP) 108 109 // Gets the class name from a view definition. 110 #define PERFETTO_TP_VIEW_CLASS_EXTRACT(class_name, ...) class_name 111 112 // Gets the view name from the view definition. 113 #define PERFETTO_TP_VIEW_NAME_EXTRACT(_, view_name) view_name 114 115 // Defines a table pointer for the macro constructor. 116 #define PERFETTO_TP_VIEW_CLASS_TABLE_COMMA_FROM(class_name, table_name, ...) \ 117 class_name *table_name, 118 119 // Defines a table pointer for the macro constructor. 120 #define PERFETTO_TP_VIEW_CLASS_TABLE_COMMA_JOIN(class_name, table_name, ...) \ 121 class_name *table_name, 122 123 // Defines a View table for the FROM table. 124 #define PERFETTO_TP_VIEW_FROM_PTR_NAME(_, table_name, ...) \ 125 table_name, #table_name 126 127 // Defines a View::Join struct for a join defined in the macro. 128 #define PERFETTO_TP_VIEW_JOIN_DEFN(_, join_table, join_col, prev_table, \ 129 prev_col, flags) \ 130 View::JoinTable{join_table, #join_table, #join_col, \ 131 #prev_table, #prev_col, flags}, 132 133 // Defines a View::Column struct for a column defined in the macro. 134 #define PERFETTO_TP_VIEW_COLUMN_DEFN(col_name, source_table, source_col) \ 135 View::OutputColumn{#col_name, TableName::source_table(), #source_col}, 136 137 // Defines a View::Column struct for a column defined in the FROM table. 138 #define PERFETTO_TP_VIEW_FROM_COLUMN_DEFN(_, col_name, ...) \ 139 PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE(PERFETTO_TP_VIEW_COLUMN_DEFN, \ 140 col_name) 141 142 // Define a TableType alias for the FROM table. 143 #define PERFETTO_TP_VIEW_TABLE_TYPE(class_name, table_name, ...) \ 144 using table_name = class_name; 145 146 // Define a special "from_table" TableType alias for the "FROM" table. 147 #define PERFETTO_TP_VIEW_TABLE_TYPE_FROM_ALIAS(_, table_name, ...) \ 148 using from_table = table_name; 149 150 // Defines the table name for each table in the view. 151 #define PERFETTO_TP_VIEW_TABLE_NAME(_, table_name, ...) \ 152 static constexpr const char* table_name() { return #table_name; } 153 154 // Define a special "from_table" TableType alias for the "FROM" table. 155 #define PERFETTO_TP_VIEW_TABLE_NAME_FROM_ALIAS(_, table_name, ...) \ 156 static constexpr const char* from_table() { return #table_name; } 157 158 // Define a ColumnType alias for each column. 159 #define PERFETTO_TP_VIEW_COLUMN_TYPE(col_name, source_table, source_col) \ 160 using col_name = typename TableType::source_table::ColumnType::source_col; 161 162 // Define a ColumnType alias for each column in the FROM table. 163 #define PERFETTO_TP_VIEW_FROM_COLUMN_TYPE(_, col_name, ...) \ 164 PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE(PERFETTO_TP_VIEW_COLUMN_TYPE, \ 165 col_name) 166 167 // Define a ColumnDataType alias for each column. 168 #define PERFETTO_TP_VIEW_COLUMN_DATA_TYPE(col_name, ...) \ 169 using col_name = typename ColumnType::col_name::type; 170 171 // Define a ColumnDataType alias for each column in the FROM table. 172 #define PERFETTO_TP_VIEW_FROM_COLUMN_DATA_TYPE(_, col_name, ...) \ 173 PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE( \ 174 PERFETTO_TP_VIEW_COLUMN_DATA_TYPE, col_name) 175 176 // Defines an enum member for each column name. 177 #define PERFETTO_TP_VIEW_COLUMN_ENUM_INDEX(col_name, ...) col_name, 178 179 // Defines an enum member for each column name in the FROM table.. 180 #define PERFETTO_TP_VIEW_FROM_COLUMN_ENUM_INDEX(_, col_name, ...) \ 181 PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE( \ 182 PERFETTO_TP_VIEW_COLUMN_ENUM_INDEX, col_name) 183 184 // Defines a column index alias for a column in the view. 185 #define PERFETTO_TP_VIEW_COLUMN_INDEX(col_name, ...) \ 186 static constexpr uint32_t col_name = \ 187 static_cast<uint32_t>(ColumnEnumIndex::col_name); 188 189 // Defines a column index alias for a column in the FROM table. 190 #define PERFETTO_TP_VIEW_FROM_COLUMN_INDEX(_, col_name, ...) \ 191 PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE( \ 192 PERFETTO_TP_VIEW_COLUMN_INDEX, col_name) 193 194 // Defines a getter in QueryResult for a column in the view. 195 #define PERFETTO_TP_VIEW_COLUMN_QUERY_RESULT_GETTER(col_name, ...) \ 196 const ColumnType::col_name& col_name() const { \ 197 return *ColumnType::col_name::FromColumn( \ 198 &columns()[ColumnIndex::col_name]); \ 199 } 200 201 // Defines a getter in QueryResult for a column in the FROM table. 202 #define PERFETTO_TP_VIEW_FROM_COLUMN_QUERY_RESULT_GETTER(_, col_name, ...) \ 203 PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE( \ 204 PERFETTO_TP_VIEW_COLUMN_QUERY_RESULT_GETTER, col_name) 205 206 // Defines a getter for the blueprint for each column. 207 #define PERFETTO_TP_VIEW_COL_BLUEPRINT_GETTER(col_name, ...) \ 208 macros_internal::ViewColumnBlueprint<ColumnDataType::col_name> col_name() \ 209 const { \ 210 return macros_internal::ViewColumnBlueprint<ColumnDataType::col_name>( \ 211 ColumnIndex::col_name); \ 212 } 213 214 // Defines a getter for the blueprint for each column in the FROM table. 215 #define PERFETTO_TP_VIEW_FROM_COLUMN_BLUEPRINT_GETTER(_, col_name, ...) \ 216 PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE( \ 217 PERFETTO_TP_VIEW_COL_BLUEPRINT_GETTER, col_name) 218 219 // Defines a getter for a column in the RowReference. 220 #define PERFETTO_TP_VIEW_COLUMN_ROW_REF_GETTER(col_name, ...) \ 221 ColumnDataType::col_name col_name() const { \ 222 return table_->col_name()[row_number_]; \ 223 } 224 // Defines a getter for a FROM column in the RowReference. 225 #define PERFETTO_TP_VIEW_FROM_COLUMN_ROW_REF_GETTER(_, col_name, ...) \ 226 PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE( \ 227 PERFETTO_TP_VIEW_COLUMN_ROW_REF_GETTER, col_name) 228 229 // Defines a getter for a column in the Iterator. 230 #define PERFETTO_TP_VIEW_COLUMN_IT_GETTER(col_name, ...) \ 231 ColumnDataType::col_name col_name() const { \ 232 const auto& col = table_->col_name(); \ 233 return col.GetAtIdx(its_[col.overlay_index()].index()); \ 234 } 235 // Defines a getter for a FROM column in the RowReference. 236 #define PERFETTO_TP_VIEW_FROM_COLUMN_IT_GETTER(_, col_name, ...) \ 237 PERFETTO_TP_VIEW_INVOKE_VIEW_COL_FN_FROM_TABLE( \ 238 PERFETTO_TP_VIEW_COLUMN_IT_GETTER, col_name) 239 240 // Defines a static assert for ensuring a given join clause is valid. 241 #define PERFETTO_TP_VIEW_JOIN_STATIC_ASSERT(_, join_table, join_col, \ 242 prev_table, prev_col, flags) \ 243 static_assert( \ 244 std::is_same< \ 245 TableType::join_table::ColumnType::join_col::type, \ 246 TableType::prev_table::ColumnType::prev_col::type>::value || \ 247 (((flags)&View::JoinFlag::kTypeCheckSerialized) != 0 && \ 248 std::is_same< \ 249 TableType::join_table::ColumnType::join_col::stored_type, \ 250 TableType::prev_table::ColumnType::prev_col::stored_type>:: \ 251 value), \ 252 "Both sides of join do not have the same type; check that you are " \ 253 "joining the correct tables and columns."); 254 255 #define PERFETTO_TP_VIEW_INTERNAL(view_name, class_name, DEF) \ 256 class class_name : public View { \ 257 public: \ 258 class RowReference; \ 259 class RowNumber; \ 260 class Iterator; \ 261 class QueryResult; \ 262 \ 263 private: \ 264 struct TableType { \ 265 PERFETTO_TP_VIEW_FROM(DEF, PERFETTO_TP_VIEW_TABLE_TYPE) \ 266 PERFETTO_TP_VIEW_JOINS(DEF, PERFETTO_TP_VIEW_TABLE_TYPE) \ 267 PERFETTO_TP_VIEW_FROM(DEF, PERFETTO_TP_VIEW_TABLE_TYPE_FROM_ALIAS) \ 268 }; \ 269 \ 270 struct TableName { \ 271 PERFETTO_TP_VIEW_FROM(DEF, PERFETTO_TP_VIEW_TABLE_NAME) \ 272 PERFETTO_TP_VIEW_JOINS(DEF, PERFETTO_TP_VIEW_TABLE_NAME) \ 273 PERFETTO_TP_VIEW_FROM(DEF, PERFETTO_TP_VIEW_TABLE_NAME_FROM_ALIAS) \ 274 }; \ 275 \ 276 enum class ColumnEnumIndex { \ 277 PERFETTO_TP_VIEW_COLUMNS(DEF, \ 278 PERFETTO_TP_VIEW_FROM_COLUMN_ENUM_INDEX, \ 279 PERFETTO_TP_VIEW_COLUMN_ENUM_INDEX) \ 280 }; \ 281 struct ColumnType { \ 282 PERFETTO_TP_VIEW_COLUMNS(DEF, \ 283 PERFETTO_TP_VIEW_FROM_COLUMN_TYPE, \ 284 PERFETTO_TP_VIEW_COLUMN_TYPE) \ 285 }; \ 286 struct ColumnDataType { \ 287 PERFETTO_TP_VIEW_COLUMNS(DEF, \ 288 PERFETTO_TP_VIEW_FROM_COLUMN_DATA_TYPE, \ 289 PERFETTO_TP_VIEW_COLUMN_DATA_TYPE) \ 290 }; \ 291 \ 292 /* Aliases to reduce clutter in class defintions below. */ \ 293 using AbstractRowNumber = \ 294 macros_internal::AbstractRowNumber<QueryResult, RowReference>; \ 295 using AbstractConstRowReference = \ 296 macros_internal::AbstractConstRowReference<QueryResult, RowNumber>; \ 297 using AbstractConstIterator = macros_internal:: \ 298 AbstractConstIterator<Iterator, QueryResult, RowNumber, RowReference>; \ 299 \ 300 public: \ 301 struct ColumnIndex { \ 302 PERFETTO_TP_VIEW_COLUMNS(DEF, \ 303 PERFETTO_TP_VIEW_FROM_COLUMN_INDEX, \ 304 PERFETTO_TP_VIEW_COLUMN_INDEX) \ 305 }; \ 306 class RowNumber : public AbstractRowNumber { \ 307 public: \ 308 explicit RowNumber(uint32_t row_number) \ 309 : AbstractRowNumber(row_number) {} \ 310 }; \ 311 static_assert(std::is_trivially_destructible<RowNumber>::value, \ 312 "Inheritance used without trivial destruction"); \ 313 \ 314 class RowReference : public AbstractConstRowReference { \ 315 public: \ 316 RowReference(const QueryResult* table, uint32_t row_number) \ 317 : AbstractConstRowReference(table, row_number) {} \ 318 \ 319 PERFETTO_TP_VIEW_COLUMNS(DEF, \ 320 PERFETTO_TP_VIEW_FROM_COLUMN_ROW_REF_GETTER, \ 321 PERFETTO_TP_VIEW_COLUMN_ROW_REF_GETTER) \ 322 }; \ 323 static_assert(std::is_trivially_destructible<RowReference>::value, \ 324 "Inheritance used without trivial destruction"); \ 325 \ 326 class Iterator : public AbstractConstIterator { \ 327 public: \ 328 PERFETTO_TP_VIEW_COLUMNS(DEF, \ 329 PERFETTO_TP_VIEW_FROM_COLUMN_IT_GETTER, \ 330 PERFETTO_TP_VIEW_COLUMN_IT_GETTER) \ 331 \ 332 Iterator& operator++() { \ 333 row_number_++; \ 334 return AbstractConstIterator::operator++(); \ 335 } \ 336 \ 337 protected: \ 338 /* \ 339 * Must not be public to avoid buggy code because of inheritance \ 340 * without virtual destructor. \ 341 */ \ 342 explicit Iterator(const QueryResult* table, \ 343 std::vector<ColumnStorageOverlay> overlays) \ 344 : AbstractConstIterator(table, std::move(overlays)) {} \ 345 \ 346 private: \ 347 friend class QueryResult; \ 348 friend class AbstractConstIterator; \ 349 \ 350 uint32_t CurrentRowNumber() const { return row_number_; } \ 351 \ 352 uint32_t row_number_ = 0; \ 353 }; \ 354 \ 355 class QueryResult : public Table { \ 356 public: \ 357 QueryResult(QueryResult&& other) = default; \ 358 QueryResult& operator=(QueryResult&& other) noexcept = default; \ 359 \ 360 ~QueryResult() override; \ 361 \ 362 PERFETTO_TP_VIEW_COLUMNS( \ 363 DEF, \ 364 PERFETTO_TP_VIEW_FROM_COLUMN_QUERY_RESULT_GETTER, \ 365 PERFETTO_TP_VIEW_COLUMN_QUERY_RESULT_GETTER) \ 366 \ 367 class_name::Iterator IterateRows() { \ 368 return class_name::Iterator(this, CopyOverlays()); \ 369 } \ 370 \ 371 private: \ 372 friend class class_name; \ 373 \ 374 QueryResult() = default; \ 375 QueryResult(Table&& table) : Table(std::move(table)) {} \ 376 }; \ 377 \ 378 class_name( \ 379 PERFETTO_TP_VIEW_FROM(DEF, PERFETTO_TP_VIEW_CLASS_TABLE_COMMA_FROM) \ 380 PERFETTO_TP_VIEW_JOINS(DEF, \ 381 PERFETTO_TP_VIEW_CLASS_TABLE_COMMA_JOIN) \ 382 std::nullptr_t = nullptr) \ 383 : View(PERFETTO_TP_VIEW_FROM(DEF, PERFETTO_TP_VIEW_FROM_PTR_NAME), \ 384 {PERFETTO_TP_VIEW_JOINS(DEF, PERFETTO_TP_VIEW_JOIN_DEFN)}, \ 385 {PERFETTO_TP_VIEW_COLUMNS(DEF, \ 386 PERFETTO_TP_VIEW_FROM_COLUMN_DEFN, \ 387 PERFETTO_TP_VIEW_COLUMN_DEFN)}) { \ 388 PERFETTO_TP_VIEW_JOINS(DEF, PERFETTO_TP_VIEW_JOIN_STATIC_ASSERT) \ 389 } \ 390 ~class_name() override; \ 391 \ 392 QueryResult Query(const std::vector<Constraint>& cs, \ 393 const std::vector<Order>& ob, \ 394 const BitVector& cols_used) const { \ 395 QueryResult result; \ 396 new (&result) QueryResult(View::Query(cs, ob, cols_used)); \ 397 return result; \ 398 } \ 399 \ 400 PERFETTO_TP_VIEW_COLUMNS(DEF, \ 401 PERFETTO_TP_VIEW_FROM_COLUMN_BLUEPRINT_GETTER, \ 402 PERFETTO_TP_VIEW_COL_BLUEPRINT_GETTER) \ 403 \ 404 static const char* Name() { return view_name; } \ 405 } 406 407 } // namespace macros_internal 408 } // namespace trace_processor 409 } // namespace perfetto 410 411 #endif // SRC_TRACE_PROCESSOR_VIEWS_MACROS_INTERNAL_H_ 412