Files
email-tracker/external/duckdb/extension/parquet/include/parquet_decimal_utils.hpp
2025-10-24 19:21:19 -05:00

56 lines
1.5 KiB
C++

//===----------------------------------------------------------------------===//
// DuckDB
//
// parquet_decimal_utils.hpp
//
//
//===----------------------------------------------------------------------===//
#pragma once
#include "column_reader.hpp"
#include "reader/templated_column_reader.hpp"
namespace duckdb {
class ParquetDecimalUtils {
public:
template <class PHYSICAL_TYPE>
static PHYSICAL_TYPE ReadDecimalValue(const_data_ptr_t pointer, idx_t size, const ParquetColumnSchema &) {
PHYSICAL_TYPE res = 0;
auto res_ptr = (uint8_t *)&res;
bool positive = (*pointer & 0x80) == 0;
// numbers are stored as two's complement so some muckery is required
for (idx_t i = 0; i < MinValue<idx_t>(size, sizeof(PHYSICAL_TYPE)); i++) {
auto byte = *(pointer + (size - i - 1));
res_ptr[i] = positive ? byte : byte ^ 0xFF;
}
// Verify that there are only 0s here
if (size > sizeof(PHYSICAL_TYPE)) {
for (idx_t i = sizeof(PHYSICAL_TYPE); i < size; i++) {
auto byte = *(pointer + (size - i - 1));
if (!positive) {
byte ^= 0xFF;
}
if (byte != 0) {
throw InvalidInputException("Invalid decimal encoding in Parquet file");
}
}
}
if (!positive) {
res += 1;
return -res;
}
return res;
}
static unique_ptr<ColumnReader> CreateReader(ParquetReader &reader, const ParquetColumnSchema &schema);
};
template <>
double ParquetDecimalUtils::ReadDecimalValue(const_data_ptr_t pointer, idx_t size, const ParquetColumnSchema &schema);
} // namespace duckdb