• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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