1 /*
2 * Copyright (C) 2023 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 #ifndef SRC_TRACE_PROCESSOR_DB_STORAGE_VARIANTS_H_
17 #define SRC_TRACE_PROCESSOR_DB_STORAGE_VARIANTS_H_
18
19 #include <variant>
20 #include "perfetto/ext/base/status_or.h"
21 #include "src/trace_processor/db/column.h"
22 #include "src/trace_processor/db/storage.h"
23
24 namespace perfetto {
25 namespace trace_processor {
26 namespace column {
27
28 // All viable numeric values for ColumnTypes.
29 using NumericValue = std::variant<uint32_t, int32_t, int64_t, double_t>;
30
31 // Using the fact that binary operators in std are operators() of classes, we
32 // can wrap those classes in variants and use them for std::visit in
33 // SerialComparators. This helps prevent excess templating and switches.
34 template <typename T>
35 using FilterOpVariant = std::variant<std::greater<T>,
36 std::greater_equal<T>,
37 std::less<T>,
38 std::less_equal<T>,
39 std::equal_to<T>,
40 std::not_equal_to<T>>;
41
42 // Based on SqlValue and ColumnType, casts SqlValue to proper type, returns
43 // std::nullopt if SqlValue can't be cast and should be considered invalid for
44 // comparison.
GetNumericTypeVariant(ColumnType type,SqlValue val)45 inline std::optional<NumericValue> GetNumericTypeVariant(ColumnType type,
46 SqlValue val) {
47 if (val.is_null())
48 return std::nullopt;
49
50 switch (type) {
51 case ColumnType::kDouble:
52 return val.AsDouble();
53 case ColumnType::kInt64:
54 return val.AsLong();
55 case ColumnType::kInt32:
56 if (val.AsLong() > std::numeric_limits<int32_t>::max() ||
57 val.AsLong() < std::numeric_limits<int32_t>::min())
58 return std::nullopt;
59 return static_cast<int32_t>(val.AsLong());
60 case ColumnType::kUint32:
61 if (val.AsLong() > std::numeric_limits<uint32_t>::max() ||
62 val.AsLong() < std::numeric_limits<uint32_t>::min())
63 return std::nullopt;
64 return static_cast<uint32_t>(val.AsLong());
65 case ColumnType::kString:
66 case ColumnType::kDummy:
67 case ColumnType::kId:
68 return std::nullopt;
69 }
70 PERFETTO_FATAL("For GCC");
71 }
72
73 // Based on SqlValue and ColumnType, casts SqlValue to proper type, returns
74 // std::nullopt if SqlValue can't be cast and should be considered invalid for
75 // comparison.
GetNumericTypeVariant(ColumnType type)76 inline std::optional<NumericValue> GetNumericTypeVariant(ColumnType type) {
77 return GetNumericTypeVariant(type, SqlValue::Long(0));
78 }
79
80 // Fetch std binary comparator class based on FilterOp. Can be used in
81 // std::visit for comparison.
82 template <typename T>
GetFilterOpVariant(FilterOp op)83 inline FilterOpVariant<T> GetFilterOpVariant(FilterOp op) {
84 switch (op) {
85 case FilterOp::kEq:
86 return FilterOpVariant<T>(std::equal_to<T>());
87 case FilterOp::kNe:
88 return FilterOpVariant<T>(std::not_equal_to<T>());
89 case FilterOp::kGe:
90 return FilterOpVariant<T>(std::greater_equal<T>());
91 case FilterOp::kGt:
92 return FilterOpVariant<T>(std::greater<T>());
93 case FilterOp::kLe:
94 return FilterOpVariant<T>(std::less_equal<T>());
95 case FilterOp::kLt:
96 return FilterOpVariant<T>(std::less<T>());
97 case FilterOp::kGlob:
98 case FilterOp::kIsNotNull:
99 case FilterOp::kIsNull:
100 PERFETTO_FATAL("Not a valid operation on numeric type.");
101 }
102 PERFETTO_FATAL("For GCC");
103 }
104
105 } // namespace column
106 } // namespace trace_processor
107 } // namespace perfetto
108 #endif // SRC_TRACE_PROCESSOR_DB_STORAGE_VARIANTS_H_
109