• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #ifndef SRC_TRACE_PROCESSOR_DB_COLUMN_H_
18 #define SRC_TRACE_PROCESSOR_DB_COLUMN_H_
19 
20 #include <stdint.h>
21 #include <optional>
22 
23 #include "perfetto/base/logging.h"
24 #include "perfetto/trace_processor/basic_types.h"
25 #include "src/trace_processor/containers/row_map.h"
26 #include "src/trace_processor/containers/string_pool.h"
27 #include "src/trace_processor/db/column_storage.h"
28 #include "src/trace_processor/db/column_storage_overlay.h"
29 #include "src/trace_processor/db/compare.h"
30 #include "src/trace_processor/db/typed_column_internal.h"
31 
32 namespace perfetto {
33 namespace trace_processor {
34 
35 // Represents the possible filter operations on a column.
36 enum class FilterOp {
37   kEq,
38   kNe,
39   kGt,
40   kLt,
41   kGe,
42   kLe,
43   kIsNull,
44   kIsNotNull,
45   kGlob,
46 };
47 
48 // Represents a constraint on a column.
49 struct Constraint {
50   uint32_t col_idx;
51   FilterOp op;
52   SqlValue value;
53 };
54 
55 // Represents an order by operation on a column.
56 struct Order {
57   uint32_t col_idx;
58   bool desc;
59 };
60 
61 // The enum type of the column.
62 // Public only to stop GCC complaining about templates being defined in a
63 // non-namespace scope (see ColumnTypeHelper below).
64 enum class ColumnType {
65   // Standard primitive types.
66   kInt32,
67   kUint32,
68   kInt64,
69   kDouble,
70   kString,
71 
72   // Types generated on the fly.
73   kId,
74 
75   // Types which don't have any data backing them.
76   kDummy,
77 };
78 
79 // Helper class for converting a type to a ColumnType.
80 template <typename T>
81 struct ColumnTypeHelper;
82 template <>
83 struct ColumnTypeHelper<int32_t> {
84   static constexpr ColumnType ToColumnType() { return ColumnType::kInt32; }
85 };
86 template <>
87 struct ColumnTypeHelper<uint32_t> {
88   static constexpr ColumnType ToColumnType() { return ColumnType::kUint32; }
89 };
90 template <>
91 struct ColumnTypeHelper<int64_t> {
92   static constexpr ColumnType ToColumnType() { return ColumnType::kInt64; }
93 };
94 template <>
95 struct ColumnTypeHelper<double> {
96   static constexpr ColumnType ToColumnType() { return ColumnType::kDouble; }
97 };
98 template <>
99 struct ColumnTypeHelper<StringPool::Id> {
100   static constexpr ColumnType ToColumnType() { return ColumnType::kString; }
101 };
102 template <typename T>
103 struct ColumnTypeHelper<std::optional<T>> : public ColumnTypeHelper<T> {};
104 
105 class Table;
106 
107 // Represents a named, strongly typed list of data.
108 class Column {
109  public:
110   // Flags which indicate properties of the data in the column. These features
111   // are used to speed up column methods like filtering/sorting.
112   enum Flag : uint32_t {
113     // Indicates that this column has no special properties.
114     kNoFlag = 0,
115 
116     // Indicates the data in the column is sorted. This can be used to speed
117     // up filtering and skip sorting.
118     kSorted = 1 << 0,
119 
120     // Indicates the data in the column is non-null. That is, the NullableVector
121     // passed in will never have any null entries. This is only used for
122     // numeric columns (string columns and id columns both have special
123     // handling which ignores this flag).
124     //
125     // This is used to speed up filters as we can safely index NullableVector
126     // directly if this flag is set.
127     kNonNull = 1 << 1,
128 
129     // Indicates that the data in the column is "hidden". This can by used to
130     // hint to users of Table and Column that this column should not be
131     // displayed to the user as it is part of the internal implementation
132     // details of the table.
133     kHidden = 1 << 2,
134 
135     // Indicates that the data in this column is stored densely. This
136     // allows for fast Set calls to change the data in the column.
137     //
138     // This flag is only meaningful for nullable columns has no effect for
139     // non-null columns.
140     kDense = 1 << 3,
141 
142     // Indicates that the sorted numeric data in the column is laid out such
143     // that at row i, we will always have col[i] <= i and the first element, j
144     // of each group happens at the index j.
145     //
146     // This is a common pattern in trace processor and columns with this
147     // property are suffixed with "set_id" hence the name of this flag.
148     //
149     // To make this clear, here are some valid and invalid uses of this flag.
150     //
151     // Valid:
152     // []
153     // [0]
154     // [0, 1, 2]
155     // [0, 0, 2]
156     // [0, 0, 0, 3, 3, 5, 6, 6, 7]
157     //
158     // Invalid:
159     // [1]
160     // [0, 0, 1]
161     // [0, 0, 2, 5]
162     // [0, 0, 2, 1]
163     //
164     // If this flag is set, kSorted and kNonNull should be set. Moreover, this
165     // flag can only be set when the type is ColumnType::kUint32; other types
166     // are not supported.
167     kSetId = 1 << 4,
168   };
169 
170   // Iterator over a column which conforms to std iterator interface
171   // to allow using std algorithms (e.g. upper_bound, lower_bound etc.).
172   class Iterator {
173    public:
174     using iterator_category = std::random_access_iterator_tag;
175     using value_type = SqlValue;
176     using difference_type = uint32_t;
177     using pointer = uint32_t*;
178     using reference = uint32_t&;
179 
180     Iterator(const Column* col, uint32_t row) : col_(col), row_(row) {}
181 
182     Iterator(const Iterator&) = default;
183     Iterator& operator=(const Iterator&) = default;
184 
185     bool operator==(const Iterator& other) const { return other.row_ == row_; }
186     bool operator!=(const Iterator& other) const { return !(*this == other); }
187     bool operator<(const Iterator& other) const { return row_ < other.row_; }
188     bool operator>(const Iterator& other) const { return other < *this; }
189     bool operator<=(const Iterator& other) const { return !(other < *this); }
190     bool operator>=(const Iterator& other) const { return !(*this < other); }
191 
192     SqlValue operator*() const { return col_->Get(row_); }
193     Iterator& operator++() {
194       row_++;
195       return *this;
196     }
197     Iterator& operator--() {
198       row_--;
199       return *this;
200     }
201 
202     Iterator& operator+=(uint32_t diff) {
203       row_ += diff;
204       return *this;
205     }
206     uint32_t operator-(const Iterator& other) const {
207       return row_ - other.row_;
208     }
209 
210     uint32_t row() const { return row_; }
211 
212    private:
213     const Column* col_ = nullptr;
214     uint32_t row_ = 0;
215   };
216 
217   // Flags specified for an id column.
218   static constexpr uint32_t kIdFlags = Flag::kSorted | Flag::kNonNull;
219 
220   // Flags which should *not* be inherited implicitly when a column is
221   // assocaited to another table.
222   static constexpr uint32_t kNoCrossTableInheritFlags = Column::Flag::kSetId;
223 
224   template <typename T>
225   Column(const char* name,
226          ColumnStorage<T>* storage,
227          /* Flag */ uint32_t flags,
228          Table* table,
229          uint32_t col_idx_in_table,
230          uint32_t row_map_idx)
231       : Column(name,
232                ColumnTypeHelper<stored_type<T>>::ToColumnType(),
233                flags,
234                table,
235                col_idx_in_table,
236                row_map_idx,
237                storage) {}
238 
239   // Create a Column backed by the same data as |column| but is associated to a
240   // different table and, optionally, having a different name.
241   Column(const Column& column,
242          Table* table,
243          uint32_t col_idx_in_table,
244          uint32_t row_map_idx,
245          const char* name = nullptr);
246 
247   // Columns are movable but not copyable.
248   Column(Column&&) noexcept = default;
249   Column& operator=(Column&&) = default;
250 
251   // Creates a Column which does not have any data backing it.
252   static Column DummyColumn(const char* name,
253                             Table* table,
254                             uint32_t col_idx_in_table);
255 
256   // Creates a Column which returns the index as the value of the row.
257   static Column IdColumn(Table* table,
258                          uint32_t col_idx_in_table,
259                          uint32_t row_map_idx);
260 
261   // Gets the value of the Column at the given |row|.
262   SqlValue Get(uint32_t row) const { return GetAtIdx(overlay().Get(row)); }
263 
264   // Returns the row containing the given value in the Column.
265   std::optional<uint32_t> IndexOf(SqlValue value) const {
266     switch (type_) {
267       // TODO(lalitm): investigate whether we could make this more efficient
268       // by first checking the type of the column and comparing explicitly
269       // based on that type.
270       case ColumnType::kInt32:
271       case ColumnType::kUint32:
272       case ColumnType::kInt64:
273       case ColumnType::kDouble:
274       case ColumnType::kString: {
275         for (uint32_t i = 0; i < overlay().size(); i++) {
276           if (compare::SqlValue(Get(i), value) == 0)
277             return i;
278         }
279         return std::nullopt;
280       }
281       case ColumnType::kId: {
282         if (value.type != SqlValue::Type::kLong)
283           return std::nullopt;
284         return overlay().RowOf(static_cast<uint32_t>(value.long_value));
285       }
286       case ColumnType::kDummy:
287         PERFETTO_FATAL("IndexOf not allowed on dummy column");
288     }
289     PERFETTO_FATAL("For GCC");
290   }
291 
292   // Sorts |idx| in ascending or descending order (determined by |desc|) based
293   // on the contents of this column.
294   void StableSort(bool desc, std::vector<uint32_t>* idx) const;
295 
296   // Updates the given RowMap by only keeping rows where this column meets the
297   // given filter constraint.
298   void FilterInto(FilterOp op, SqlValue value, RowMap* rm) const {
299     if (IsId() && op == FilterOp::kEq) {
300       // If this is an equality constraint on an id column, try and find the
301       // single row with the id (if it exists).
302       auto opt_idx = IndexOf(value);
303       if (opt_idx) {
304         rm->IntersectExact(*opt_idx);
305       } else {
306         rm->Clear();
307       }
308       return;
309     }
310 
311     if (IsSetId() && op == FilterOp::kEq && value.type == SqlValue::kLong) {
312       // If the column is sorted and the value has the same type as the column,
313       // we should be able to just do a binary search to find the range of rows
314       // instead of a full table scan.
315       FilterIntoSetIdEq(value.AsLong(), rm);
316       return;
317     }
318 
319     if (IsSorted() && value.type == type()) {
320       // If the column is sorted and the value has the same type as the column,
321       // we should be able to just do a binary search to find the range of rows
322       // instead of a full table scan.
323       bool handled = FilterIntoSorted(op, value, rm);
324       if (handled)
325         return;
326     }
327 
328     FilterIntoSlow(op, value, rm);
329   }
330 
331   // Returns the minimum value in this column. Returns std::nullopt if this
332   // column is empty.
333   std::optional<SqlValue> Min() const {
334     if (overlay().empty())
335       return std::nullopt;
336 
337     if (IsSorted())
338       return Get(0);
339 
340     Iterator b(this, 0);
341     Iterator e(this, overlay().size());
342     return *std::min_element(b, e, &compare::SqlValueComparator);
343   }
344 
345   // Returns the minimum value in this column. Returns std::nullopt if this
346   // column is empty.
347   std::optional<SqlValue> Max() const {
348     if (overlay().empty())
349       return std::nullopt;
350 
351     if (IsSorted())
352       return Get(overlay().size() - 1);
353 
354     Iterator b(this, 0);
355     Iterator e(this, overlay().size());
356     return *std::max_element(b, e, &compare::SqlValueComparator);
357   }
358 
359   // Returns the backing RowMap for this Column.
360   // This function is defined out of line because of a circular dependency
361   // between |Table| and |Column|.
362   const ColumnStorageOverlay& overlay() const;
363 
364   // Returns the name of the column.
365   const char* name() const { return name_; }
366 
367   // Returns the type of this Column in terms of SqlValue::Type.
368   SqlValue::Type type() const { return ToSqlValueType(type_); }
369 
370   // Returns the type of this Column in terms of ColumnType.
371   ColumnType col_type() const { return type_; }
372 
373   // Test the type of this Column.
374   template <typename T>
375   bool IsColumnType() const {
376     return ColumnTypeHelper<T>::ToColumnType() == type_;
377   }
378 
379   // Returns true if this column is considered an id column.
380   bool IsId() const { return type_ == ColumnType::kId; }
381 
382   // Returns true if this column is a nullable column.
383   bool IsNullable() const { return IsNullable(flags_); }
384 
385   // Returns true if this column is a sorted column.
386   bool IsSorted() const { return IsSorted(flags_); }
387 
388   // Returns true if this column is a dense column.
389   bool IsDense() const { return IsDense(flags_); }
390 
391   // Returns true if this column is a set id column.
392   // Public for testing.
393   bool IsSetId() const { return IsSetId(flags_); }
394 
395   // Returns true if this column is a dummy column.
396   // Public for testing.
397   bool IsDummy() const { return type_ == ColumnType::kDummy; }
398 
399   // Returns the index of the RowMap in the containing table.
400   uint32_t overlay_index() const { return overlay_index_; }
401 
402   // Returns the index of the current column in the containing table.
403   uint32_t index_in_table() const { return index_in_table_; }
404 
405   // Returns a Constraint for each type of filter operation for this Column.
406   Constraint eq_value(SqlValue value) const {
407     return Constraint{index_in_table_, FilterOp::kEq, value};
408   }
409   Constraint gt_value(SqlValue value) const {
410     return Constraint{index_in_table_, FilterOp::kGt, value};
411   }
412   Constraint lt_value(SqlValue value) const {
413     return Constraint{index_in_table_, FilterOp::kLt, value};
414   }
415   Constraint ne_value(SqlValue value) const {
416     return Constraint{index_in_table_, FilterOp::kNe, value};
417   }
418   Constraint ge_value(SqlValue value) const {
419     return Constraint{index_in_table_, FilterOp::kGe, value};
420   }
421   Constraint le_value(SqlValue value) const {
422     return Constraint{index_in_table_, FilterOp::kLe, value};
423   }
424   Constraint is_not_null() const {
425     return Constraint{index_in_table_, FilterOp::kIsNotNull, SqlValue()};
426   }
427   Constraint is_null() const {
428     return Constraint{index_in_table_, FilterOp::kIsNull, SqlValue()};
429   }
430 
431   // Returns an Order for each Order type for this Column.
432   Order ascending() const { return Order{index_in_table_, false}; }
433   Order descending() const { return Order{index_in_table_, true}; }
434 
435   // Returns an iterator to the first entry in this column.
436   Iterator begin() const { return Iterator(this, 0); }
437 
438   // Returns an iterator pointing beyond the last entry in this column.
439   Iterator end() const { return Iterator(this, overlay().size()); }
440 
441   // Returns whether the given combination of flags when the column has the
442   // given type is valid.
443   template <typename T>
444   static constexpr bool IsFlagsAndTypeValid(uint32_t flags) {
445     return IsFlagsAndTypeValid(flags, ColumnTypeHelper<T>::ToColumnType());
446   }
447 
448   template <typename T>
449   using stored_type = typename tc_internal::TypeHandler<T>::stored_type;
450 
451   // Returns the backing sparse vector cast to contain data of type T.
452   // Should only be called when |type_| == ToColumnType<T>().
453   template <typename T>
454   const ColumnStorage<stored_type<T>>& storage() const {
455     PERFETTO_DCHECK(ColumnTypeHelper<T>::ToColumnType() == type_);
456     PERFETTO_DCHECK(tc_internal::TypeHandler<T>::is_optional == IsNullable());
457     return *static_cast<ColumnStorage<stored_type<T>>*>(storage_);
458   }
459 
460  protected:
461   // Returns the backing sparse vector cast to contain data of type T.
462   // Should only be called when |type_| == ToColumnType<T>().
463   template <typename T>
464   ColumnStorage<stored_type<T>>* mutable_storage() {
465     PERFETTO_DCHECK(ColumnTypeHelper<T>::ToColumnType() == type_);
466     PERFETTO_DCHECK(tc_internal::TypeHandler<T>::is_optional == IsNullable());
467     return static_cast<ColumnStorage<stored_type<T>>*>(storage_);
468   }
469 
470   // Returns true if this column is a hidden column.
471   bool IsHidden() const { return (flags_ & Flag::kHidden) != 0; }
472 
473   const StringPool& string_pool() const { return *string_pool_; }
474 
475   // Returns the type of this Column in terms of SqlValue::Type.
476   template <typename T>
477   static SqlValue::Type ToSqlValueType() {
478     return ToSqlValueType(ColumnTypeHelper<T>::ToColumnType());
479   }
480 
481   static SqlValue ToSqlValue(double value) { return SqlValue::Double(value); }
482   static SqlValue ToSqlValue(int32_t value) { return SqlValue::Long(value); }
483   static SqlValue ToSqlValue(uint32_t value) { return SqlValue::Long(value); }
484   static SqlValue ToSqlValue(int64_t value) { return SqlValue::Long(value); }
485   static SqlValue ToSqlValue(NullTermStringView value) {
486     return SqlValue::String(value.c_str());
487   }
488 
489  private:
490   friend class Table;
491   friend class View;
492 
493   // Base constructor for this class which all other constructors call into.
494   Column(const char* name,
495          ColumnType type,
496          uint32_t flags,
497          Table* table,
498          uint32_t col_idx_in_table,
499          uint32_t overlay_index,
500          ColumnStorageBase* nullable_vector);
501 
502   Column(const Column&) = delete;
503   Column& operator=(const Column&) = delete;
504 
505   // Gets the value of the Column at the given |idx|.
506   SqlValue GetAtIdx(uint32_t idx) const {
507     switch (type_) {
508       case ColumnType::kInt32:
509         return GetAtIdxTyped<int32_t>(idx);
510       case ColumnType::kUint32:
511         return GetAtIdxTyped<uint32_t>(idx);
512       case ColumnType::kInt64:
513         return GetAtIdxTyped<int64_t>(idx);
514       case ColumnType::kDouble:
515         return GetAtIdxTyped<double>(idx);
516       case ColumnType::kString: {
517         auto str = GetStringPoolStringAtIdx(idx).c_str();
518         return str == nullptr ? SqlValue() : SqlValue::String(str);
519       }
520       case ColumnType::kId:
521         return SqlValue::Long(idx);
522       case ColumnType::kDummy:
523         PERFETTO_FATAL("GetAtIdx not allowed on dummy column");
524     }
525     PERFETTO_FATAL("For GCC");
526   }
527 
528   template <typename T>
529   SqlValue GetAtIdxTyped(uint32_t idx) const {
530     if (IsNullable()) {
531       auto opt_value = storage<std::optional<T>>().Get(idx);
532       return opt_value ? ToSqlValue(*opt_value) : SqlValue();
533     }
534     return ToSqlValue(storage<T>().Get(idx));
535   }
536 
537   // Optimized filter method for sorted columns.
538   // Returns whether the constraint was handled by the method.
539   bool FilterIntoSorted(FilterOp op, SqlValue value, RowMap* rm) const {
540     PERFETTO_DCHECK(IsSorted());
541     PERFETTO_DCHECK(value.type == type());
542 
543     Iterator b(this, 0);
544     Iterator e(this, overlay().size());
545     switch (op) {
546       case FilterOp::kEq: {
547         uint32_t beg = std::distance(
548             b, std::lower_bound(b, e, value, &compare::SqlValueComparator));
549         uint32_t end = std::distance(
550             b, std::upper_bound(b, e, value, &compare::SqlValueComparator));
551         rm->Intersect({beg, end});
552         return true;
553       }
554       case FilterOp::kLe: {
555         uint32_t end = std::distance(
556             b, std::upper_bound(b, e, value, &compare::SqlValueComparator));
557         rm->Intersect({0, end});
558         return true;
559       }
560       case FilterOp::kLt: {
561         uint32_t end = std::distance(
562             b, std::lower_bound(b, e, value, &compare::SqlValueComparator));
563         rm->Intersect({0, end});
564         return true;
565       }
566       case FilterOp::kGe: {
567         uint32_t beg = std::distance(
568             b, std::lower_bound(b, e, value, &compare::SqlValueComparator));
569         rm->Intersect({beg, overlay().size()});
570         return true;
571       }
572       case FilterOp::kGt: {
573         uint32_t beg = std::distance(
574             b, std::upper_bound(b, e, value, &compare::SqlValueComparator));
575         rm->Intersect({beg, overlay().size()});
576         return true;
577       }
578       case FilterOp::kNe:
579       case FilterOp::kIsNull:
580       case FilterOp::kIsNotNull:
581       case FilterOp::kGlob:
582         break;
583     }
584     return false;
585   }
586 
587   void FilterIntoSetIdEq(int64_t value, RowMap* rm) const {
588     PERFETTO_DCHECK(!IsNullable());
589 
590     uint32_t filter_set_id = static_cast<uint32_t>(value);
591     const auto& st = storage<uint32_t>();
592     const ColumnStorageOverlay& ov = overlay();
593 
594     // If the set id is beyond the end of the column, there's no chance that
595     // it exists.
596     if (PERFETTO_UNLIKELY(filter_set_id >= st.size())) {
597       rm->Clear();
598       return;
599     }
600 
601     uint32_t set_id = st.Get(ov.Get(filter_set_id));
602 
603     // If the set at that index does not equal the set id we're looking for, the
604     // set id doesn't exist either.
605     if (PERFETTO_UNLIKELY(set_id != filter_set_id)) {
606       PERFETTO_DCHECK(set_id < filter_set_id);
607       rm->Clear();
608       return;
609     }
610 
611     // Otherwise, find the end of the set and return the intersection for this.
612     for (uint32_t i = set_id + 1; i < ov.size(); ++i) {
613       if (st.Get(ov.Get(i)) != filter_set_id) {
614         RowMap r(set_id, i);
615         rm->Intersect(r);
616         return;
617       }
618     }
619     RowMap r(set_id, ov.size());
620     rm->Intersect(r);
621   }
622 
623   // Slow path filter method which will perform a full table scan.
624   void FilterIntoSlow(FilterOp op, SqlValue value, RowMap* rm) const;
625 
626   // Slow path filter method for numerics which will perform a full table scan.
627   template <typename T, bool is_nullable>
628   void FilterIntoNumericSlow(FilterOp op, SqlValue value, RowMap* rm) const;
629 
630   // Slow path filter method for numerics with a comparator which will perform a
631   // full table scan.
632   template <typename T, bool is_nullable, typename Comparator = int(T)>
633   void FilterIntoNumericWithComparatorSlow(FilterOp op,
634                                            RowMap* rm,
635                                            Comparator cmp) const;
636 
637   // Slow path filter method for strings which will perform a full table scan.
638   void FilterIntoStringSlow(FilterOp op, SqlValue value, RowMap* rm) const;
639 
640   // Slow path filter method for ids which will perform a full table scan.
641   void FilterIntoIdSlow(FilterOp op, SqlValue value, RowMap* rm) const;
642 
643   // Stable sorts this column storing the result in |out|.
644   template <bool desc>
645   void StableSort(std::vector<uint32_t>* out) const;
646 
647   // Stable sorts this column storing the result in |out|.
648   // |T| and |is_nullable| should match the type and nullability of this column.
649   template <bool desc, typename T, bool is_nullable>
650   void StableSortNumeric(std::vector<uint32_t>* out) const;
651 
652   static constexpr bool IsDense(uint32_t flags) {
653     return (flags & Flag::kDense) != 0;
654   }
655   static constexpr bool IsNullable(uint32_t flags) {
656     return (flags & Flag::kNonNull) == 0;
657   }
658   static constexpr bool IsSetId(uint32_t flags) {
659     return (flags & Flag::kSetId) != 0;
660   }
661   static constexpr bool IsSorted(uint32_t flags) {
662     return (flags & Flag::kSorted) != 0;
663   }
664 
665   static constexpr bool IsFlagsAndTypeValid(uint32_t flags, ColumnType type) {
666     return (!IsDense(flags) || IsFlagsForDenseValid(flags)) &&
667            (!IsSetId(flags) || IsFlagsAndTypeForSetIdValid(flags, type));
668   }
669 
670   static constexpr bool IsFlagsForDenseValid(uint32_t flags) {
671     // The dense flag should only be set when the column is nullable.
672     return IsNullable(flags);
673   }
674 
675   static constexpr bool IsFlagsAndTypeForSetIdValid(uint32_t flags,
676                                                     ColumnType type) {
677     // The sorted flag should always be set for set id columns.
678     // The non-null flag should always be set for set id columns.
679     // The column type should always be kUint32.
680     return IsSorted(flags) && !IsNullable(flags) && type == ColumnType::kUint32;
681   }
682 
683   static SqlValue::Type ToSqlValueType(ColumnType type) {
684     switch (type) {
685       case ColumnType::kInt32:
686       case ColumnType::kUint32:
687       case ColumnType::kInt64:
688       case ColumnType::kId:
689         return SqlValue::Type::kLong;
690       case ColumnType::kDouble:
691         return SqlValue::Type::kDouble;
692       case ColumnType::kString:
693         return SqlValue::Type::kString;
694       case ColumnType::kDummy:
695         PERFETTO_FATAL("ToSqlValueType not allowed on dummy column");
696     }
697     PERFETTO_FATAL("For GCC");
698   }
699 
700   // Returns the string at the index |idx|.
701   // Should only be called when |type_| == ColumnType::kString.
702   NullTermStringView GetStringPoolStringAtIdx(uint32_t idx) const {
703     PERFETTO_DCHECK(type_ == ColumnType::kString);
704     return string_pool_->Get(storage<StringPool::Id>().Get(idx));
705   }
706 
707   // type_ is used to cast nullable_vector_ to the correct type.
708   ColumnType type_ = ColumnType::kInt64;
709   ColumnStorageBase* storage_ = nullptr;
710 
711   const char* name_ = nullptr;
712   uint32_t flags_ = Flag::kNoFlag;
713   const Table* table_ = nullptr;
714   uint32_t index_in_table_ = 0;
715   uint32_t overlay_index_ = 0;
716   const StringPool* string_pool_ = nullptr;
717 };
718 
719 }  // namespace trace_processor
720 }  // namespace perfetto
721 
722 #endif  // SRC_TRACE_PROCESSOR_DB_COLUMN_H_
723