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