| 371 | } |
| 372 | |
| 373 | std::optional<CompressionMetadata> ConstantCompression::analyze(const ColumnChunkData& chunk) { |
| 374 | switch (chunk.getDataType().getPhysicalType()) { |
| 375 | // Only values that can fit in the CompressionMetadata's data field can use constant |
| 376 | // compression |
| 377 | case PhysicalTypeID::BOOL: { |
| 378 | if (chunk.getCapacity() == 0) { |
| 379 | return std::optional( |
| 380 | CompressionMetadata(StorageValue(0), StorageValue(0), CompressionType::CONSTANT)); |
| 381 | } |
| 382 | auto firstValue = chunk.getValue<bool>(0); |
| 383 | |
| 384 | // TODO(bmwinger): This could be optimized. We could do bytewise comparison with memcmp, |
| 385 | // but we need to make sure to stop at the end of the values to avoid false positives |
| 386 | for (auto i = 1u; i < chunk.getNumValues(); i++) { |
| 387 | // If any value is different from the first one, we can't use constant compression |
| 388 | if (firstValue != chunk.getValue<bool>(i)) { |
| 389 | return std::nullopt; |
| 390 | } |
| 391 | } |
| 392 | auto value = StorageValue(firstValue); |
| 393 | return std::optional(CompressionMetadata(value, value, CompressionType::CONSTANT)); |
| 394 | } |
| 395 | case PhysicalTypeID::INTERNAL_ID: |
| 396 | case PhysicalTypeID::DOUBLE: |
| 397 | case PhysicalTypeID::FLOAT: |
| 398 | case PhysicalTypeID::UINT8: |
| 399 | case PhysicalTypeID::UINT16: |
| 400 | case PhysicalTypeID::UINT32: |
| 401 | case PhysicalTypeID::UINT64: |
| 402 | case PhysicalTypeID::INT8: |
| 403 | case PhysicalTypeID::INT16: |
| 404 | case PhysicalTypeID::INT32: |
| 405 | case PhysicalTypeID::INT64: |
| 406 | case PhysicalTypeID::INT128: { |
| 407 | uint8_t size = chunk.getNumBytesPerValue(); |
| 408 | StorageValue value{}; |
| 409 | DASSERT(size <= sizeof(value.unsignedInt)); |
| 410 | // If there are no values, or only one value, we will always use constant compression |
| 411 | // since the loop won't execute |
| 412 | for (auto i = 1u; i < chunk.getNumValues(); i++) { |
| 413 | // If any value is different from the first one, we can't use constant compression |
| 414 | if (std::memcmp(chunk.getData(), chunk.getData() + i * size, size) != 0) { |
| 415 | return std::nullopt; |
| 416 | } |
| 417 | } |
| 418 | if (chunk.getNumValues() > 0) { |
| 419 | std::memcpy(&value.unsignedInt, chunk.getData(), size); |
| 420 | } |
| 421 | return std::optional(CompressionMetadata(value, value, CompressionType::CONSTANT)); |
| 422 | } |
| 423 | default: { |
| 424 | return std::optional<CompressionMetadata>(); |
| 425 | } |
| 426 | } |
| 427 | } |
| 428 | |
| 429 | uint64_t Uncompressed::numValues(uint64_t dataSize, common::PhysicalTypeID physicalType) { |
| 430 | uint32_t numBytesPerValue = getDataTypeSizeInChunk(physicalType); |
nothing calls this directly
no test coverage detected