| 1164 | } |
| 1165 | |
| 1166 | std::pair<std::optional<StorageValue>, std::optional<StorageValue>> getMinMaxStorageValue( |
| 1167 | const uint8_t* data, uint64_t offset, uint64_t numValues, PhysicalTypeID physicalType, |
| 1168 | const NullMask* nullMask, bool valueRequiredIfUnsupported) { |
| 1169 | std::pair<std::optional<StorageValue>, std::optional<StorageValue>> returnValue; |
| 1170 | |
| 1171 | TypeUtils::visit( |
| 1172 | physicalType, |
| 1173 | [&](bool) { |
| 1174 | if (numValues > 0) { |
| 1175 | const auto boolData = reinterpret_cast<const uint64_t*>(data); |
| 1176 | if (!nullMask || nullMask->hasNoNullsGuarantee()) { |
| 1177 | auto [minRaw, maxRaw] = NullMask::getMinMax(boolData, offset, numValues); |
| 1178 | returnValue = std::make_pair(std::optional(StorageValue(minRaw)), |
| 1179 | std::optional(StorageValue(maxRaw))); |
| 1180 | } else { |
| 1181 | std::optional<StorageValue> min, max; |
| 1182 | for (size_t i = offset; i < offset + numValues; i++) { |
| 1183 | if (!nullMask || !nullMask->isNull(i)) { |
| 1184 | auto boolValue = NullMask::isNull(boolData, i); |
| 1185 | if (!max || boolValue > max->get<bool>()) { |
| 1186 | max = boolValue; |
| 1187 | } |
| 1188 | if (!min || boolValue < min->get<bool>()) { |
| 1189 | min = boolValue; |
| 1190 | } |
| 1191 | } |
| 1192 | } |
| 1193 | returnValue = std::make_pair(min, max); |
| 1194 | } |
| 1195 | } |
| 1196 | }, |
| 1197 | [&]<typename T>(T) |
| 1198 | requires(numeric_utils::IsIntegral<T> || std::floating_point<T>) |
| 1199 | { |
| 1200 | if (numValues > 0) { |
| 1201 | auto typedData = std::span(reinterpret_cast<const T*>(data) + offset, numValues); |
| 1202 | returnValue = getTypedMinMax(typedData, nullMask ? &*nullMask : nullptr, offset); |
| 1203 | } |
| 1204 | }, |
| 1205 | [&]<typename T>(T) |
| 1206 | requires(std::same_as<T, internalID_t>) |
| 1207 | { |
| 1208 | if (numValues > 0) { |
| 1209 | const auto typedData = |
| 1210 | std::span(reinterpret_cast<const uint64_t*>(data) + offset, numValues); |
| 1211 | returnValue = getTypedMinMax(typedData, nullMask ? &*nullMask : nullptr, offset); |
| 1212 | } |
| 1213 | }, |
| 1214 | [&]<typename T>(T) |
| 1215 | requires(std::same_as<T, interval_t> || std::same_as<T, struct_entry_t> || |
| 1216 | std::same_as<T, string_t> || std::same_as<T, list_entry_t> || |
| 1217 | std::same_as<T, uint128_t>) |
| 1218 | { |
| 1219 | if (valueRequiredIfUnsupported) { |
| 1220 | // For unsupported types on the first copy, |
| 1221 | // they need a non-optional value to distinguish them |
| 1222 | // from supported types where every value is null |
| 1223 | returnValue.first = std::numeric_limits<uint64_t>::min(); |
no test coverage detected