1 /* 2 * Copyright (C) 2020 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_TYPED_COLUMN_INTERNAL_H_ 18 #define SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_INTERNAL_H_ 19 20 #include "src/trace_processor/db/column.h" 21 22 namespace perfetto { 23 namespace trace_processor { 24 namespace tc_internal { 25 26 // Serializer converts between the "public" type used by the rest of trace 27 // processor and the type we store in the NullableVector. 28 template <typename T, typename Enabled = void> 29 struct Serializer { 30 using serialized_type = T; 31 SerializeSerializer32 static serialized_type Serialize(T value) { return value; } DeserializeSerializer33 static T Deserialize(serialized_type value) { return value; } 34 SerializeSerializer35 static base::Optional<serialized_type> Serialize(base::Optional<T> value) { 36 return value; 37 } DeserializeSerializer38 static base::Optional<T> Deserialize(base::Optional<serialized_type> value) { 39 return value; 40 } 41 }; 42 43 template <typename T> 44 using is_id = std::is_base_of<BaseId, T>; 45 46 // Specialization of Serializer for id types. 47 template <typename T> 48 struct Serializer<T, typename std::enable_if<is_id<T>::value>::type> { 49 using serialized_type = uint32_t; 50 51 static serialized_type Serialize(T value) { return value.value; } 52 static T Deserialize(serialized_type value) { return T{value}; } 53 54 static base::Optional<serialized_type> Serialize(base::Optional<T> value) { 55 return value ? base::make_optional(Serialize(*value)) : base::nullopt; 56 } 57 static base::Optional<T> Deserialize(base::Optional<serialized_type> value) { 58 return value ? base::make_optional(Deserialize(*value)) : base::nullopt; 59 } 60 }; 61 62 // Specialization of Serializer for StringPool types. 63 template <> 64 struct Serializer<StringPool::Id> { 65 using serialized_type = StringPool::Id; 66 67 static serialized_type Serialize(StringPool::Id value) { return value; } 68 static StringPool::Id Deserialize(serialized_type value) { return value; } 69 70 static serialized_type Serialize(base::Optional<StringPool::Id> value) { 71 // Since StringPool::Id == 0 is always treated as null, rewrite 72 // base::nullopt -> 0 to remove an extra check at filter time for 73 // base::nullopt. Instead, that code can assume that the NullableVector 74 // layer always returns a valid id and can handle the nullability at the 75 // stringpool level. 76 // TODO(lalitm): remove this special casing if we migrate all tables over 77 // to macro tables and find that we can remove support for null stringids 78 // in the stringpool. 79 return value ? Serialize(*value) : StringPool::Id::Null(); 80 } 81 static base::Optional<serialized_type> Deserialize( 82 base::Optional<StringPool::Id> value) { 83 return value; 84 } 85 }; 86 87 // TypeHandler (and it's specializations) allow for specialied handling of 88 // functions of a TypedColumn based on what is being stored inside. 89 // Default implementation of TypeHandler. 90 template <typename T, typename Enable = void> 91 struct TypeHandler { 92 using non_optional_type = T; 93 using get_type = T; 94 using sql_value_type = 95 typename Serializer<non_optional_type>::serialized_type; 96 97 static constexpr bool is_optional = false; 98 static constexpr bool is_string = false; 99 100 template <typename SerializedType> 101 static SerializedType Get(const NullableVector<SerializedType>& nv, 102 uint32_t idx) { 103 return nv.GetNonNull(idx); 104 } 105 106 static bool Equals(T a, T b) { 107 // We need to use equal_to here as it could be T == double and because we 108 // enable all compile time warnings, we will get complaints if we just use 109 // a == b. 110 return std::equal_to<T>()(a, b); 111 } 112 }; 113 114 // Specialization for Optional types. 115 template <typename T> 116 struct TypeHandler<base::Optional<T>> { 117 using non_optional_type = T; 118 using get_type = base::Optional<T>; 119 using sql_value_type = 120 typename Serializer<non_optional_type>::serialized_type; 121 122 static constexpr bool is_optional = true; 123 static constexpr bool is_string = false; 124 125 template <typename SerializedType> 126 static base::Optional<SerializedType> Get( 127 const NullableVector<SerializedType>& nv, 128 uint32_t idx) { 129 return nv.Get(idx); 130 } 131 132 static bool Equals(base::Optional<T> a, base::Optional<T> b) { 133 // We need to use equal_to here as it could be T == double and because we 134 // enable all compile time warnings, we will get complaints if we just use 135 // a == b. This is the same reason why we can't also just use equal_to using 136 // a and b directly because the optional implementation of equality uses 137 // == which again causes complaints. 138 return a.has_value() == b.has_value() && 139 (!a.has_value() || std::equal_to<T>()(*a, *b)); 140 } 141 }; 142 143 // Specialization for Optional<StringId> types. 144 template <> 145 struct TypeHandler<StringPool::Id> { 146 // get_type removes the base::Optional since we convert base::nullopt -> 147 // StringPool::Id::Null (see Serializer<StringPool> above). 148 using non_optional_type = StringPool::Id; 149 using get_type = StringPool::Id; 150 using sql_value_type = NullTermStringView; 151 152 static constexpr bool is_optional = false; 153 static constexpr bool is_string = true; 154 155 static StringPool::Id Get(const NullableVector<StringPool::Id>& nv, 156 uint32_t idx) { 157 return nv.GetNonNull(idx); 158 } 159 160 static bool Equals(StringPool::Id a, StringPool::Id b) { return a == b; } 161 }; 162 163 // Specialization for Optional<StringId> types. 164 template <> 165 struct TypeHandler<base::Optional<StringPool::Id>> { 166 // get_type removes the base::Optional since we convert base::nullopt -> 167 // StringPool::Id::Null (see Serializer<StringPool> above). 168 using non_optional_type = StringPool::Id; 169 using get_type = base::Optional<StringPool::Id>; 170 using sql_value_type = NullTermStringView; 171 172 // is_optional is false again because we always unwrap 173 // base::Optional<StringPool::Id> into StringPool::Id. 174 static constexpr bool is_optional = false; 175 static constexpr bool is_string = true; 176 177 static base::Optional<StringPool::Id> Get( 178 const NullableVector<StringPool::Id>& nv, 179 uint32_t idx) { 180 StringPool::Id id = nv.GetNonNull(idx); 181 return id.is_null() ? base::nullopt : base::make_optional(id); 182 } 183 184 static bool Equals(base::Optional<StringPool::Id> a, 185 base::Optional<StringPool::Id> b) { 186 // To match our handling of treating base::nullopt == 187 // StringPool::Id::Null(), ensure that they both compare equal to each 188 // other. 189 return a == b || (!a && b->is_null()) || (!b && a->is_null()); 190 } 191 }; 192 193 } // namespace tc_internal 194 } // namespace trace_processor 195 } // namespace perfetto 196 197 #endif // SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_INTERNAL_H_ 198